如何从 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 个项目(placeTitle
和 placeDesc
)显示到列表视图中。我无法将数据加载到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(使用自定义数组适配器)的主要内容,如果未能解决你的问题,请参考以下文章