自定义Dialog的onCreateView先返回,Firestore数据未加载致无视图显示
解决Firestore异步加载数据导致Dialog中RecyclerView无数据的问题
我明白你的困扰了——Firestore的数据获取是异步操作,而onCreateView会同步执行并返回视图,等到Firestore返回数据时,Dialog已经显示出来了,这时候才设置adapter可能不会触发UI更新。咱们一步步来修复这个问题:
问题根源
databaseTeachers.collection("Teachers").get()是异步任务,它的onComplete回调会在后台数据请求完成后才执行,但onCreateView会先完成并返回rootView。所以Dialog初始化时RecyclerView并没有绑定adapter,后续即使设置了adapter,也可能因为没有主动通知UI刷新而看不到数据。
解决方案
我们需要提前初始化RecyclerView的adapter和数据列表,等Firestore返回数据后,更新列表并通知adapter刷新UI:
- 提前初始化数据列表和adapter:在
onCreateView开头就创建空的teacherLists和对应的adapter,并绑定到RecyclerView上。 - 数据返回后更新列表并刷新adapter:在Firestore的
onComplete回调里,清空旧列表、添加新数据,然后调用adapter.notifyDataSetChanged()通知UI更新。 - 优化Firebase初始化逻辑:简化重复初始化的判断代码,让它更简洁。
修改后的完整代码
import android.app.DialogFragment; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Toast; import com.crashlytics.android.Crashlytics; import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.Task; import com.google.firebase.FirebaseApp; import com.google.firebase.FirebaseOptions; import com.google.firebase.firestore.FirebaseFirestore; import com.google.firebase.firestore.FirebaseFirestoreSettings; import com.google.firebase.firestore.QuerySnapshot; import java.util.ArrayList; import java.util.List; import io.fabric.sdk.android.Fabric; public class DialogSetClassTeacher extends DialogFragment { private RecyclerView recyclerView; private SetClassTeacherListAdapter adapter; private FirebaseFirestore databaseTeachers; private List<ClassTeacher> teacherLists; FirebaseApp smaTeacher; @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { Fabric.with(this.getActivity(), new Crashlytics()); final View rootView = inflater.inflate(R.layout.dialog_set_class_teacher, container, false); // 1. 提前初始化空数据列表和adapter teacherLists = new ArrayList<>(); adapter = new SetClassTeacherListAdapter(getActivity(), teacherLists); // 初始化RecyclerView并绑定adapter recyclerView = rootView.findViewById(R.id.dialogSetClassTeacherRecycleView); recyclerView.setLayoutManager(new LinearLayoutManager(this.getActivity())); recyclerView.setAdapter(adapter); this.getDialog().setTitle("Select a Class Teacher"); // 简化Firebase初始化逻辑 FirebaseOptions options = new FirebaseOptions.Builder() .setDatabaseUrl(getResources().getString(R.string.dbURL)) .setApiKey(getResources().getString(R.string.api)) .setApplicationId(getResources().getString(R.string.appID)) .setProjectId(getResources().getString(R.string.projectId)) .setStorageBucket(getResources().getString(R.string.storageBucket)) .build(); FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder() .setPersistenceEnabled(true) .build(); // 避免重复初始化的简化判断 if (FirebaseApp.getApps(getActivity()).stream().noneMatch(app -> app.getName().equals("SMA_Teachers"))) { smaTeacher = FirebaseApp.initializeApp(getActivity(), options, "SMA_Teachers"); } else { smaTeacher = FirebaseApp.getInstance("SMA_Teachers"); } databaseTeachers = FirebaseFirestore.getInstance(smaTeacher); databaseTeachers.setFirestoreSettings(settings); // 2. 异步获取Firestore数据,更新列表并刷新adapter databaseTeachers.collection("Teachers").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() { @Override public void onComplete(@NonNull Task<QuerySnapshot> task) { if (task.isSuccessful()) { teacherLists.clear(); // 清空旧数据 for (DocumentSnapshot doc : task.getResult()) { ClassTeacher newDataList = new ClassTeacher(doc.getString("name"), " ", doc.getString("email")); teacherLists.add(newDataList); } Toast.makeText(getActivity(), "数据加载完成", Toast.LENGTH_SHORT).show(); adapter.notifyDataSetChanged(); // 通知adapter刷新UI } else { Toast.makeText(getActivity(), "Error : " + task.getException().getMessage(), Toast.LENGTH_SHORT).show(); } } }); return rootView; } }
额外提示
- 确保你的
SetClassTeacherListAdapter正确处理了列表数据的更新,比如在构造方法里持有列表的引用,而不是拷贝一份。 - 如果需要优化加载体验,可以在Dialog里添加一个加载进度条,在Firestore请求开始时显示,请求完成后隐藏。
内容的提问来源于stack exchange,提问作者Deepak Kumar
相关产品推荐
相关产品推荐

