Android ListView 未填充

Android ListView does not populate

我在 fragment 上有两个按钮,一个按钮使用 SQLite 显示 listview,另一个按钮使用 Firebase 显示 listview . listviewSQLite 有效,但是,尽管逻辑相同,但 listviewFirebase 无效。我可以从 firebase 中成功检索数据(我使用 Toast 对其进行了测试,它工作得很好),但是不知何故,我无法在 listview.[=27= 中显示检索到的数据]

这里是片段的全部代码,包括 listview for SQLiteFirebase:

package com.example.dailybible3;

import android.content.Intent;
import android.database.Cursor;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;

import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;

import java.util.ArrayList;


public class FragmentNotes extends Fragment {

    private static final String TAG = "";
    private View view;
    private Button btn_all_notes, btn_my_notes;
    DatabaseHelper mDatabaseHelper;
    private ListView mListView;
    ListAdapter adapter;
    ArrayList<String> listData, listData2;

    public static FragmentNotes newInstance() {
        FragmentNotes fragmentNotes = new FragmentNotes();
        return fragmentNotes;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        view = inflater.inflate(R.layout.fragment_notes, container, false);

        //SQL
        mListView = (ListView) view.findViewById(R.id.list_view);
        mDatabaseHelper = new DatabaseHelper(getActivity());

        populatePrivateListView();

        //all note button
        btn_all_notes = (Button) view.findViewById(R.id.btn_all_notes);
        btn_all_notes.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                populatePublicListView();
            }
        });

        //my note button
        btn_my_notes = (Button) view.findViewById(R.id.btn_my_notes);
        btn_my_notes.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                populatePrivateListView();
            }
        });

        //floating button
        FloatingActionButton fab = view.findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startActivity(new Intent(getActivity(), MyNotes.class));
            }
        });

        return view;
    }


    private void populatePrivateListView() {
        Log.d(TAG, "populatePrivateListView: Displaying PRIVATE data in the ListView.");

        //get the data and append to a list
        Cursor cursor = mDatabaseHelper.getData();
        listData = new ArrayList<>();

        while(cursor.moveToNext()){
            //get the value from the database in column 1
            //then add it to the ArrayList
            listData.add(cursor.getString(1));
        }

        //create the list adapter and set the adapter
        //customize the listview with "list_view_item"
        adapter = new ArrayAdapter<String>(getContext(),R.layout.list_view_items, listData);
        mListView.setAdapter(adapter);

        //set an onItemClickListener to the ListView
        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                String name = adapterView.getItemAtPosition(i).toString();
                Log.d(TAG, "onItemClick: You Clicked on " + name);

                Cursor data = mDatabaseHelper.getItemID(name); //get the id associated with that name
                int itemID = -1;
                while(data.moveToNext()){
                    itemID = data.getInt(0);
                }
                if(itemID > -1){
                    Log.d(TAG, "onItemClick: The ID is: " + itemID);
                    Intent editPrivateData  = new Intent(getActivity(), FragmentNotesEditPrivateData.class);
                    editPrivateData.putExtra("id", itemID);
                    editPrivateData.putExtra("name", name);
                    startActivity(editPrivateData);

                }
                else{
                    toastMessage("No ID associated with that name");
                }
            }
        });
    }

    private void populatePublicListView() {
        DatabaseReference firebase;

        firebase = FirebaseDatabase.getInstance().getReference().child("Note");

        //set the listview
        listData2 = new ArrayList<>();

        firebase.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                String note = snapshot.getValue().toString();
                listData2.add(note);
                toastMessage(note);
            }
            @Override
            public void onCancelled(@NonNull DatabaseError error) {

            }
        });

        //set the listview
        adapter = new ArrayAdapter<String>(getContext(),R.layout.list_view_items, listData2);
        mListView.setAdapter(adapter);
    }

    /**
     * customizable toast
     * @param message
     */
    private void toastMessage(String message){
        Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT).show();
    }
}

这不起作用,因为您的“适配器”在某些情况下可能为 null 或未定义,这可能就是您正在发生的情况。要解决这个问题,您需要记住听众的工作就是听您的代码。所以,你的

String note = snapshot.getValue().toString();
                listData2.add(note);
                toastMessage(note);

仅在侦听器检测到快照发生变化时实施。我没有亲自实施您的代码或对其进行测试,因此无法说明更多漏洞。但是我可以立即想到的一种解决方案是这样的(不完全是)。您可能需要尝试并使 listData2 静态化或将适配器放在 Listener 之外以避免内存泄漏。试试看是否有效。

  firebase.addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(@NonNull DataSnapshot snapshot) {
                    String note = snapshot.getValue().toString();
                    listData2.add(note);
                    toastMessage(note);
                    adapter = new ArrayAdapter<String>(getContext(),R.layout.list_view_items, listData2);
                    mListView.setAdapter(adapter);
                }
                @Override
                public void onCancelled(@NonNull DatabaseError error) {
    
                }
            });
    
            //set the listview