如何从 Firebase 检索数据到 ListView(使用自定义数组适配器)

Posted

技术标签:

【中文标题】如何从 Firebase 检索数据到 ListView(使用自定义数组适配器)【英文标题】:How to retrieve data from Firebase into a ListView (with custom Array Adapter) 【发布时间】:2020-11-05 20:22:09 【问题描述】:

我目前设计了一个地点浏览器应用程序,其中 3 个项目显示在列表视图中。当用户登录时,他会找到一个类别列表。单击一个类别时,将显示该类别下的地点列表。我已将该应用与 Firebase 相关联。

现在,我想将存储在 firebase 中的数据中的 2 个项目(placeTitleplaceDesc)显示到列表视图中。我无法将数据加载到ListView

购物活动:

public class ShoppingActivity extends AppCompatActivity 

    DatabaseReference databaseReference;
    Place shopping;
    ListView listView;
    ArrayList<Place> list;
    ArrayAdapter <Place> adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.place_list);
        getWindow().getDecorView().setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);

        //For accessing firebase data and load into Listview
        list = new ArrayList<>();
        shopping = new Place();
        listView = findViewById(R.id.listView); //listview
        adapter = new ArrayAdapter<>(this, R.layout.custom_list_item, list);
        final PlaceAdapter placeAdapter = new PlaceAdapter(this, list, R.color.category_shopping);
        databaseReference = FirebaseDatabase.getInstance().getReference("PlaceDetails"); //database reference
        databaseReference.addValueEventListener(new ValueEventListener() 
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) 
                for(DataSnapshot ds: snapshot.getChildren())

                    Place shopping = ds.getValue(Place.class);

                    if (shopping != null) 

                        list.add(new Place(shopping.getPlaceTitle(),shopping.getPlaceTitle()));
                    
                


                listView.setAdapter(placeAdapter);
            

            @Override
            public void onCancelled(@NonNull DatabaseError error) 

            
        );


        //Create a new array list of Places
//        final ArrayList<Place> shopping = new ArrayList<>();


//        Place p = new Place("State Museum","Ambari Guwahati");
//        culture.add(p);

        //create a new object for Place and add all place details
//        shopping.add(new Place("Fancy Bazar Daily Market", "Fancy Bazar Guwahati"));
//        shopping.add(new Place("Pentaloons", "Sixmile Guwahati"));
//        shopping.add(new Place("Guwahati Central", "Zoo Road Guwahati"));
//        shopping.add(new Place("Eastrends (Hub)", "Bhangagarh Guwahati"));
//        shopping.add(new Place("City Centre", "G.S. Road Guwahati"));
//        shopping.add(new Place("Central Mall", "G.S. Road Guwahati"));



//        ArrayAdapter<Place> itemsAdapter = new ArrayAdapter<Place>(this, R.layout.custom_list_item, shopping);
//
//        PlaceAdapter placeAdapter = new PlaceAdapter(this, shopping, R.color.category_shopping);
//
//        ListView listView = findViewById(R.id.listView);
//
//        listView.setAdapter(placeAdapter);


        //Displaying the listview items
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() 
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) 
                //Toast.makeText(CultureActivity.this, "ListView Item is clicked", Toast.LENGTH_SHORT).show();

                //For opening a new view in google maps
                // Get the @link Word object at the given position the user clicked on
                Place place = list.get(position);

                // Create a Uri from an intent string. Use the result to create an Intent to open the place in Google Maps
                Uri gmmIntentUri = Uri.parse("geo:0,0?q=" + Uri.encode(place.getPlaceTitle()));


                //Uri gmmIntentUri = Uri.parse("geo:0,0?place");

                //The below Intent will request turn-by-turn navigation to the Place clicked
                //Uri gmmIntentUri = Uri.parse("google.navigation:q="+Uri.encode(place.getPlaceTitle()));

                // Create an Intent from gmmIntentUri. Set the action to ACTION_VIEW
                Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri);
                // Make the Intent explicit by setting the Google Maps package
                mapIntent.setPackage("com.google.android.apps.maps");

                // Attempt to start an activity that can handle the Intent
                if (mapIntent.resolveActivity(getPackageManager()) != null) 
                    startActivity(mapIntent);

                
            
        );
    

放置对象

package android.example.com.knowguwahaticity;

import android.content.Context;

public class Place 


    //Declare the state of the Place class
    //Place Title
    private String mPlaceTitle;

    //Place Desc
    private String mPlaceDesc;

    // Drawable resource ID
    private int mImageResourceId = NO_IMAGE_PROVIDED;

    //Drawable resource ID
    private int mPlaceResourceId;

    //Image visibility
    private static final int NO_IMAGE_PROVIDED = -1 ;


    //Construct the custom class Place


    public Place() 
    

    public Place(String placeTitle, String placeDesc, int imageResourceId) 
        mPlaceTitle = placeTitle;
        mPlaceDesc = placeDesc;
        mImageResourceId = imageResourceId;
    

    public Place(String placeTitle, String placeDesc) 
        mPlaceTitle = placeTitle;
        mPlaceDesc = placeDesc;
    

    //declare the methods to access the states of the class
    //get the Title of the place
    public String getPlaceTitle() 
        return mPlaceTitle;
    

    //get the Address of the place
    public String getPlaceDesc() 
        return mPlaceDesc;
    

    //get the image resource id of the image
    public int getImageResourceId() 
        return mImageResourceId;
    

//    //get the map resource id of the image
//    public int getPlaceResourceId() 
//        return mPlaceResourceId;
//    

    //check whether the object has an image
    public boolean hasImage()
        return mImageResourceId != NO_IMAGE_PROVIDED;
    

自定义列表视图 XML

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_
    android:layout_
    android:gravity="center_vertical"
    android:minHeight="@dimen/list_item_height"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/place_image_view"
        android:layout_
        android:layout_
        android:padding="8dp"
        android:src="@drawable/star"
        />

    <LinearLayout

        android:id="@+id/text_container"
        android:layout_
        android:layout_
        android:layout_weight="1"
        android:orientation="vertical"
        android:paddingLeft="16dp">

        <TextView
            android:id="@+id/title_text_view"
            android:layout_
            android:layout_
            android:layout_weight="1"
            android:textAppearance="@style/TextAppearance.AppCompat.Medium"
            android:textColor="@android:color/white"
            android:gravity="bottom"
            android:textSize="18sp"
            android:textStyle="bold"
            tools:text="Title" />

        <TextView
            android:id="@+id/desc_text_view"
            android:layout_
            android:layout_
            android:layout_weight="1"
            android:textAppearance="@style/TextAppearance.AppCompat.Medium"
            android:textColor="@android:color/white"
            android:gravity="top|bottom"
            android:textSize="14sp"
            tools:text="Description" />

    </LinearLayout>
</LinearLayout>

PlaceAdapter.java

package android.example.com.knowguwahaticity;

import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;

import java.util.ArrayList;
import java.util.Set;

public class PlaceAdapter extends ArrayAdapter<Place> 

    /** Resource ID for the background color for this list of words */
    private int mColorResourceId;
    private Context mContext;

    public PlaceAdapter(Activity context, ArrayList<Place> places, int colorResourceId) 
        super(context, 0, places);
        mColorResourceId = colorResourceId;

    

    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) 

        View listItemView = convertView;

        if(listItemView == null) 
            listItemView = LayoutInflater.from(getContext()).inflate(
                    R.layout.custom_list_item, parent, false);
        

        //get the position of the object at this position of the list
        Place currentPlace = getItem(position);

        //Find the textview in the custom_list_item.xml with id textView1 (Title of the Place)
        TextView TitleTextView = listItemView.findViewById(R.id.title_text_view);
        TitleTextView.setText(currentPlace.getPlaceTitle());


        //Find the textview in the custom_list_item.xml with id textView2 (Desc of the place)
        TextView DescTextView = listItemView.findViewById(R.id.desc_text_view);
        DescTextView.setText(currentPlace.getPlaceDesc());

        // Find the ImageView in the list_item.xml layout with the ID list_item_icon
        ImageView iconView = (ImageView) listItemView.findViewById(R.id.place_image_view);
        // Get the image resource ID from the current Place object and
        // set the image to iconView
        if(currentPlace.hasImage()) 

            iconView.setImageResource(currentPlace.getImageResourceId());

            //set image view as visible
            iconView.setVisibility(View.VISIBLE);
        
        else 
            //set image view as GONE
            iconView.setVisibility(View.GONE);
        

        // Find the ImageView in the list_item.xml layout with the ID list_item_icon
//        ImageView mapView = (ImageView) listItemView.findViewById(R.id.place_map_view);
//        // Get the image resource ID from the current Place object and
//        // set the image to iconView
//        mapView.setImageResource(currentPlace.getPlaceResourceId());

        /*Set OnClickListener on the mapView to open the location in map app*/
//        mapView.setTag(position);
//        mapView.setOnClickListener(new View.OnClickListener() 
//
//            @Override
//            public void onClick(View view) 
//                Toast.makeText(mContext, "ImageView clicked for the row = "+view.getTag().toString(), Toast.LENGTH_SHORT).show();
//            
//        );

        // Set the theme color for the list item
        View textContainer = listItemView.findViewById(R.id.text_container);
        // Find the color that the resource ID maps to
        int color = ContextCompat.getColor(getContext(), mColorResourceId);
        // Set the background color of the text container View
        textContainer.setBackgroundColor(color);


        return listItemView;
    

【问题讨论】:

这段代码中到底有什么不符合您的预期? 我的购物活动出现空白屏幕。我正在尝试从 firebase 中提取 placeTitle 和 placeDesc 并添加到购物(Place 对象)中,然后使用 listView 显示。 【参考方案1】:

您将得到一个“空白屏幕”,因为您的类中的属性名称与数据库中的属性名称匹配。看,你的Place 类中有一个名为mPlaceTitle 的字段,而在数据库中名为placeTitle,这是正确的。为了解决这个问题,您可以简单地更改类中所有属性的名称以匹配数据库中的名称,根据Java Naming Conventions 关于变量,这些属性的名称是正确的。

【讨论】:

知道了。在我的 Firebase 中,我有 6 个字段针对子“PlaceDetails”。但我只需要其中 2 个字段来填充此活动的 listView。如何做到这一点? 您是否更改了类中的属性名称以匹配数据库中的名称?如果是,您应该遵循的下一个将在此 answer 中进行说明。 现在运行良好。问题出在我的模拟器上,我是由于互联网问题。当我在实际设备中运行时,firebase 数据正在加载。非常感谢。

以上是关于如何从 Firebase 检索数据到 ListView(使用自定义数组适配器)的主要内容,如果未能解决你的问题,请参考以下文章

如何将数据从 firebase 检索到 ListView?

如何等到从 Firebase 检索到我的数据? [复制]

如何从firebase直接检索数据到应用程序中?

如何将数据从 Firebase 检索到我的适配器

从firebase检索数据到android

如何从从 Firebase 检索信息的闭包中传递数据?