英文:
Java code working only when I set a breakpoint, not in release mode
问题
我必须在片段中的可回收视图中显示用户列表。 代码没问题,但是当我运行应用程序时列表不会显示出来。
package com.example.demo;
import android.database.Cursor;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.example.demo.Model.User;
import com.mongodb.Block;
import com.mongodb.DBObject;
import com.mongodb.stitch.android.core.Stitch;
import com.mongodb.stitch.android.core.StitchAppClient;
import com.mongodb.stitch.android.services.mongodb.remote.RemoteFindIterable;
import com.mongodb.stitch.android.services.mongodb.remote.RemoteMongoClient;
import com.mongodb.stitch.android.services.mongodb.remote.RemoteMongoCollection;
import com.mongodb.stitch.android.services.mongodb.remote.RemoteMongoCursor;
import org.bson.Document;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class UsersFragment extends Fragment {
private RecyclerView recyclerView;
private UserAdapter userAdapter = null;
private List<User> mUsers = null;
private String username;
private String imageURL;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fargment_users, container, false);
recyclerView = view.findViewById(R.id.recycler_view);
StitchAppClient stitchAppClient = Stitch.getDefaultAppClient();
RemoteMongoClient client = stitchAppClient.getServiceClient(RemoteMongoClient.factory, "mongodb-atlas");
RemoteMongoCollection<Document> db = client.getDatabase("db").getCollection("Users");
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
mUsers = new ArrayList<>();
mUsers.clear();
try {
readUsers();
} catch (InterruptedException e) {
e.printStackTrace();
}
return view;
}
private void readUsers() throws InterruptedException {
StitchAppClient stitchAppClient = Stitch.getDefaultAppClient();
RemoteMongoClient client = stitchAppClient.getServiceClient(RemoteMongoClient.factory, "mongodb-atlas");
RemoteMongoCollection<Document> db = client.getDatabase("db").getCollection("Users");
RemoteFindIterable<Document> docs = db.find();
docs.forEach(new Block<Document>() {
@Override
public void apply(Document document) {
username = document.getString("username");
imageURL = document.getString("imageURL");
Log.d("rrrrrrrr", "apply: " + username + imageURL);
User user = new User(username, imageURL);
mUsers.add(user);
Log.d("rrrrrrrr", "apply: " + mUsers);
}
});
userAdapter = new UserAdapter(getContext(), mUsers);
recyclerView.setAdapter(userAdapter);
}
}
然后我尝试对代码进行调试,并在这些行上设置了断点:
userAdapter = new UserAdapter(getContext(), mUsers);
recyclerView.setAdapter(userAdapter);
列表显示出来了。我不知道发生了什么,所以我移除了断点,代码不起作用了。然后我尝试在这一行上添加一个断点:
username = document.getString("username");
并且我逐行运行代码,发现它永远不会进入上面提到的那些行。列表仍然不显示。我尝试在这些行之间加入:
Thread.yield();
但是没有任何效果。我甚至尝试将这些行放在以下代码块之间:
getActivity().runOnUiThread(new Runnable() {...});
但没有效果。请帮忙。谢谢。
英文:
I have to show a list of users in a recycler view in a fragment. The code is fine but the list does not show up when I run the app.
package com.example.demo;
import android.database.Cursor;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.example.demo.Model.User;
import com.mongodb.Block;
import com.mongodb.DBObject;
import com.mongodb.stitch.android.core.Stitch;
import com.mongodb.stitch.android.core.StitchAppClient;
import com.mongodb.stitch.android.services.mongodb.remote.RemoteFindIterable;
import com.mongodb.stitch.android.services.mongodb.remote.RemoteMongoClient;
import com.mongodb.stitch.android.services.mongodb.remote.RemoteMongoCollection;
import com.mongodb.stitch.android.services.mongodb.remote.RemoteMongoCursor;
import org.bson.Document;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class UsersFragment extends Fragment {
private RecyclerView recyclerView;
private UserAdapter userAdapter = null;
private List<User> mUsers = null;
private String username;
private String imageURL;
@Override
public View onCreateView( LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fargment_users,container,false);
recyclerView = view.findViewById(R.id.recycler_view);
StitchAppClient stitchAppClient = Stitch.getDefaultAppClient();
RemoteMongoClient client = stitchAppClient.getServiceClient(RemoteMongoClient.factory,"mongodb-atlas");
RemoteMongoCollection db = client.getDatabase("db").getCollection("Users");
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
mUsers = new ArrayList<>();
mUsers.clear();
try {
readUsers();
} catch (InterruptedException e) {
e.printStackTrace();
}
return view;
}
private void readUsers() throws InterruptedException {
StitchAppClient stitchAppClient = Stitch.getDefaultAppClient();
RemoteMongoClient client = stitchAppClient.getServiceClient(RemoteMongoClient.factory, "mongodb-atlas");
RemoteMongoCollection db = client.getDatabase("db").getCollection("Users");
RemoteFindIterable docs = db.find();
docs.forEach(new Block<Document>() {
@Override
public void apply(Document document) {
username = document.getString("username");
imageURL = document.getString("imageURL");
Log.d("rrrrrrrr", "apply: " + username + imageURL);
User user = new User(username, imageURL);
mUsers.add(user);
Log.d("rrrrrrrr", "apply: " + mUsers);
}
});
userAdapter = new UserAdapter(getContext(), mUsers);
recyclerView.setAdapter(userAdapter);
}
}
Then I tried debugging the code and put a breakpoint on these lines
userAdapter = new UserAdapter(getContext(), mUsers);
recyclerView.setAdapter(userAdapter);
And the list showed up. I didn't know what happened so I removed the breakpoints and the code was not working.
Then I tried adding a breakpoint at
username = document.getString("username");
and I run it through each and every line and I found it never goes to those lines mentioned above.
The list was still not showing.
I tried putting
Thread.yield();
Between the lines, but nothing worked.
I even tried to put those lines between
getActivity.runOnUiThread(){new Runnable{...}}
But doesn't work.
Please help.
Thank You.
答案1
得分: 0
尝试将方法调用移到 onViewCreated()
中:
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
try {
readUsers();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
英文:
Try to move your method call in onViewCreated()
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
try {
readUsers();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
答案2
得分: 0
没有使用过MongoDB,但似乎db.find()
返回某种类型的promise集合,而你的apply(Document doc)
是异步回调。这意味着你的userAdapter始终使用空数组构造。
但在调试模式下可以工作,因为在适配器构造行上点击“Step”按钮时,异步回调已经起作用并返回了值。
未找到相关文档(甚至是否存在?),因此我将其添加到项目中,并发现你可以将**OnCompleteListener
**添加到RemoteFindIterable
。那应该是创建适配器的地方。
此外,考虑在onCreateView
中将适配器附加到RecyclerView
,但在onSuccessListener
中调用notifyDataSetChanged()
。
英文:
Haven't worked with MongoDB, but it seems like db.find()
returns a collection of some sort of promises, and your apply(Document doc)
are asynchronous callbacks. That means that your userAdapter is always constructed with empty array.
But it works in debug mode because asynchronous callbacks have worked and returned values by the time you click on the "Step" button on the adapter construction line.
Could not find the documentation for it (does it even exist?), so I added it to project and found that you can add OnCompleteListener
to the RemoteFindIterable
. That should be the place to make an adapter.
docs.forEach(new Block<Document>() {
@Override
public void apply(Document document) {
username = document.getString("username");
imageURL = document.getString("imageURL");
User user = new User(username, imageURL);
mUsers.add(user);
}
}).addOnSuccessListener(new OnSuccessListener() {
@Override
public void onSuccess(Object o) {
userAdapter = new UserAdapter(getContext(), mUsers);
recyclerView.setAdapter(userAdapter);
}
});
Also, consider attaching an adapter to RecyclerView
in onCreateView
, but in onSuccessListener
calling notifyDataSetChanged()
on it.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论