由于某些原因,列表大小返回零

时间:2020-01-17 09:51:52

标签: java android list

我正在将数据从云firestore加载到自定义的recyclerview适配器中。根据我的日志,我从firestore获得的数据很好,并且在我的get方法内部,日志显示列表大小在增加。在我的get方法之外, mWorkoutList 返回大小为0。我不知道为什么会这样。Log shows mWorkoutList size going back to 0

public class ViewWorkoutsActivity extends AppCompatActivity implements WorkoutAdapter.WorkoutAdapterOnClickHandler {

private final String TAG = this.getClass().getName();
private FirebaseFirestore db;
private String mUid;
private List<Set> mSetList;
private RecyclerView mRecyclerView;
private WorkoutAdapter mWorkoutAdapter;
private List<OtherWorkout> mWorkoutList;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_view_workouts);
    mWorkoutList = new ArrayList<>();
    mUid = getIntent().getStringExtra("uid");
    db = FirebaseFirestore.getInstance();
    initDatabaseData();

    mRecyclerView = findViewById(R.id.recycler_view);

    LinearLayoutManager linearLayoutManager
            = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
    mRecyclerView.setLayoutManager(linearLayoutManager);
    mRecyclerView.setHasFixedSize(true);
    mWorkoutAdapter = new WorkoutAdapter(this);
    mRecyclerView.setAdapter(mWorkoutAdapter);
    Log.i("LOG", "workout list size HERE: " + mWorkoutList.size());
    mWorkoutAdapter.setWorkoutData(mWorkoutList);
}

@Override
public void onClick(OtherWorkout workout) {

}

public void initDatabaseData(){
    CollectionReference collectionReference2 = db.collection("users").document(mUid).collection("workouts");
    collectionReference2.get()
            .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                @Override
                public void onComplete(@NonNull Task<QuerySnapshot> task) {
                    if(task.isSuccessful()){
                        for (QueryDocumentSnapshot document : task.getResult()){
                            OtherWorkout workout = document.toObject(OtherWorkout.class);
                            mWorkoutList.add(workout);
                            Log.i("LOG", "workout list size: " + mWorkoutList.size());
                        }
                    }
                }
            });
}
}

4 个答案:

答案 0 :(得分:2)

您好,艾伦,您正在调用initDatabaseData();在oncreate()方法中,该方法发出网络请求并获取数据。因此,大约需要2-3秒来获取数据。但是在这2-3秒内,您在initDatabaseData()下的代码被调用

 LinearLayoutManager linearLayoutManager
        = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
mRecyclerView.setLayoutManager(linearLayoutManager);
mRecyclerView.setHasFixedSize(true);
mWorkoutAdapter = new WorkoutAdapter(this);
mRecyclerView.setAdapter(mWorkoutAdapter);
Log.i("LOG", "workout list size HERE: " + mWorkoutList.size());
mWorkoutAdapter.setWorkoutData(mWorkoutList);

因此,直到数据还没有到,列表大小将显示为0,然后在onComplete()中获取数据后,列表大小将增加()。因此,基本上添加一行mWorkoutAdapter.notifyDatasetChanged();在这里:-

if(task.isSuccessful()){
                    for (QueryDocumentSnapshot document : task.getResult()){
                        OtherWorkout workout = document.toObject(OtherWorkout.class);
                        mWorkoutList.add(workout);
                        Log.i("LOG", "workout list size: " + mWorkoutList.size());
                    }mWorkoutAdapter.notifyDatasetChanged();

                }

这将使用新值刷新适配器。

答案 1 :(得分:0)

您将OtherWorkout创建为本地对象,然后将其添加到集合中。 如果您的get()函数超出范围,则该对象将被自动删除。

我没有检查,但是我认为Java垃圾回收将处理其余工作并从Array中删除对象。

您应使用new在堆上创建对象,以使它们在该函数范围之外仍然存在。

答案 2 :(得分:0)

您可以检查您的

  Log.i("LOG", "workout list size: " + mWorkoutList.size());

之后

 Log.i("LOG", "workout list size HERE: " + mWorkoutList.size());

所以这意味着firebase需要一些时间来获取所有数据,在这段时间内您的其余代码将被执行。 因此,在设置适配器之后,该解决方案称为initDatabaseData(),然后调用adapter.notifydatasetchanged()。或者您也可以在获取数据后直接通过initDatabaseData()方法通知适配器。

答案 3 :(得分:0)

addOnCompleteListener提供了一种添加异步任务侦听器的方法。

调用initDatabaseData()时,将启动任务并定义一个侦听器。但是不能保证从initDatabaseData返回时此任务已完成。

这就是为什么一旦在mWorkoutList方法中打印了onCreate大小后,该值便可能与侦听器中打印的值不同。

为避免这种情况,您可以通过将异步机制更改为同步机制,也可以通过使用侦听器onComplete方法的数据部分来更改程序的工作方式