首页 > 解决方案 > 如何从 Firebase 检索数据到 ListView(使用自定义数组适配器)

问题描述

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

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

应用快照

Firebase 快照

购物活动:

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_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:minHeight="@dimen/list_item_height"
    android:orientation="horizontal">

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

    <LinearLayout

        android:id="@+id/text_container"
        android:layout_width="0dp"
        android:layout_height="@dimen/list_item_height"
        android:layout_weight="1"
        android:orientation="vertical"
        android:paddingLeft="16dp">

        <TextView
            android:id="@+id/title_text_view"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            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_width="match_parent"
            android:layout_height="0dp"
            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;
    }
}

标签: javaandroidfirebaselistviewfirebase-realtime-database

解决方案


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


推荐阅读