全局变量在android studio中返回null [重复]

Posted

技术标签:

【中文标题】全局变量在android studio中返回null [重复]【英文标题】:Global variable is returning null in android studio [duplicate] 【发布时间】:2021-07-28 09:51:03 【问题描述】:

我正在从 Firestore 中检索医院数据。我想将检索到的数据保持为整个片段的全局,但是从 addOnSuccessListner() 出来后 Map 将返回 null。

我已经在 onCreateView() 中声明了 Map

static  Map<String, Map<String, String>> hospitals ;
public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) 
        View root = inflater.inflate(R.layout.fragment_home, container, false);
        hospitals = new HashMap<>();
        .......
        .....

        return root;

下面是我检索 HospitalData 的代码。

private void readHospitalData() 
    CollectionReference collectionReference = fStore.collection("hospital Details");
    collectionReference.get()
            .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() 
                @Override
                public void onSuccess(QuerySnapshot queryDocumentSnapshots) 
                    for(QueryDocumentSnapshot queryDocumentSnapshot: queryDocumentSnapshots)
                        Map<String, String> map = new HashMap<>();
                        map.put("h_name", queryDocumentSnapshot.getString("h_name"));
                        map.put("h_email", queryDocumentSnapshot.getString("h_email"));
                        map.put("h_phone", queryDocumentSnapshot.getString("h_phone"));
                        map.put("h_road", queryDocumentSnapshot.getString("h_road"));
                        map.put("h_area", queryDocumentSnapshot.getString("h_area"));
                        map.put("h_city", queryDocumentSnapshot.getString("h_city"));
                        map.put("h_state", queryDocumentSnapshot.getString("h_state"));
                        map.put("h_pincode", queryDocumentSnapshot.getString("h_pincode"));

                        hospitals.put(queryDocumentSnapshot.getId(), map);
                    
                    Log.d("MAP-->" , hospitals.toString());  // display the Map
                
            );
    Log.d("MAP-->" , hospitals.toString());  // but here it will display null


【问题讨论】:

它不应该为空,除非你在 onCreateView 之前调用 readHospitalData 。它将为空 collectionReference.get() 是一个异步调用,因此您只需将 Logs 放入 onSuccess 中。 您也可以查看 this 【参考方案1】:

处理读取和写入数据的 Firebase API 调用是完全异步的。这意味着调用总是立即返回,而不会阻塞代码等待结果。结果会在稍后的某个时间出现,只要他们准备好了。

这就是为什么你在这里得到空值

CollectionReference collectionReference = fStore.collection("hospital Details");
    collectionReference.get()
            .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() 
    public void onSuccess(DocumentSnapshot snapshot) 
        // handle the document snapshot here
    
);
task.addOnFailureListener(new OnFailureListener() 
    public void onFailure(Exception e) 
        // handle any errors here
    
);
    Log.d("MAP-->" , hospitals.toString());

Firebase 消费者 API 出现这种行为的原因: -> 为什么要让 API 的使用者经历使用异步 API 的额外麻烦?我们不能只使用更简单的同步 API 吗?好吧,Firebase 可以为移动应用程序提供同步 API,但是我们会继承两个问题之一,这两个问题都比编写这些额外的代码更糟糕。

1.在应用的主线程上调用同步函数可能会无限期地冻结应用,这是一种糟糕的用户体验。在 android 上,它还可能出现应用程序无响应 (ANR) 对话框软崩溃。

    为避免使用异步方法阻塞主线程,我们必须管理自己的线程才能正确调用这些 API。这甚至是更多的代码,而且很难正确处理。即使是专业工程师也面临着正确线程行为的挑战。

考虑异步!

Firebase API 对应用主线程的性能很敏感。这意味着任何需要处理磁盘或网络上的数据的 Firebase API 都是以异步方式实现的。这些函数将立即返回,因此您可以在主线程上调用它们而不必担心性能。您所要做的就是使用文档和示例中建立的模式实现回调。

这个问题有一个解决方案,你必须使用 Kotlin-Flow 进行同步调用,通过这个链接:https://developer.android.com/kotlin/flow#callback

【讨论】:

【参考方案2】:

我通过使用 Callback

解决了这个问题

我创建了 HospitalData.class 并从那里的 firebase 检索数据。通过使用 Callback 接口,我读取了 Fragment

中的数据

HospitalData.class

    public class HospitalData 
    
        FirebaseFirestore fStore = FirebaseFirestore.getInstance();
        Map<String, Map<String, String>> hospitals = new HashMap<>();
        HospitalCallback hospitalCallback;
    
        HospitalData()
            // empty constructor
        
    
        public void setHospitalCallback(HospitalCallback hospitalCallback) 
            this.hospitalCallback = hospitalCallback;
        
    
        void getHospitalData()
            CollectionReference collectionReference = fStore.collection("hospital Details");
            collectionReference.get()
                    .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() 
                        @Override
                        public void onSuccess(QuerySnapshot queryDocumentSnapshots) 
                            for(QueryDocumentSnapshot queryDocumentSnapshot: queryDocumentSnapshots) 
                                Map<String, String> map = new HashMap<>();
                                map.put("h_name", queryDocumentSnapshot.getString("h_name"));
                                map.put("h_email", queryDocumentSnapshot.getString("h_email"));
                                map.put("h_phone", queryDocumentSnapshot.getString("h_phone"));
                                map.put("h_road", queryDocumentSnapshot.getString("h_road"));
                                map.put("h_area", queryDocumentSnapshot.getString("h_area"));
                                map.put("h_city", queryDocumentSnapshot.getString("h_city"));
                                map.put("h_state", queryDocumentSnapshot.getString("h_state"));
                                map.put("h_pincode", queryDocumentSnapshot.getString("h_pincode"));
    
                                hospitals.put(queryDocumentSnapshot.getId(), map);
    
                            
                            hospitalCallback.DisplayHospitalData(hospitals);
                        
                    );
        
    
        interface HospitalCallback
            public void DisplayHospitalData(Map<String, Map<String, String>> map);
        

在我的 HomeFragment.class 中

public class HomeFragment extends Fragment implements HospitalCallback

    static  Map<String, Map<String, String>> hospitals ;
    HospitalData hospitalData;

    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) 
        View root = inflater.inflate(R.layout.fragment_home, container, false);
        hospitals = new HashMap<>();
        hospitalData = new HospitalData();
        hospitalData.getHospitalData();
        hospitalData.setHospitalCallback(this);

        return root;
    
    

    @Override
    public void DisplayHospitalData(Map<String, Map<String, String>> map) 
         Log.d("HOSPITAL DATA-->", map.toString());
    


【讨论】:

以上是关于全局变量在android studio中返回null [重复]的主要内容,如果未能解决你的问题,请参考以下文章

在Android studio 中使用单例模式

如何下载安装jdk和jre?以及配置JDK全局环境变量和安装Android studio

android studio 2018.3.20 用户输入

androidstudio调用别的界面值

android studio 开发经常使用快捷键使用分享

android studio 开发常用快捷键使用分享