Java code working only when I set a breakpoint, not in release mode

Rahul Sonia :

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.

Teempy :

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.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=410001&siteId=1