如何使用 ArrayAdapter 从 Firebase 数据库中读取数据并在 ListView 中显示多个字段
How to Read Data from Firebase Database and Display Multiple Fields in ListView with ArrayAdapter
我花了大半天的时间试图弄清楚如何从我的 firebase 数据库中读取数据并通过 ArrayAdapter
在 ListView
中显示多个字段。终于让我的 ListView 在一个文本视图中显示一条数据后,我无法尝试显示其他两个字段。
在我的 MainActivity
class 中,我在 Adapter 构造函数中使用了 android.R.layout.simple_list_item_1
,因为我被告知 textViewResourceID 参数必须只包含一个 TextView。所以重申我的问题:我无法弄清楚如何使用数组适配器显示多个字段。此应用目前仅显示 make 字段。非常感谢,我大约一周前才开始 android 开发!下面是我的代码:
SearchModel.java
public class SearchModel {
public String make;
private String model;
private String stock;
public SearchModel() {}
public String getMake() {
return this.make;
}
public void setMake(String make) {
this.make = make;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getStock() {
return stock;
}
public void setStock(String stock) {
this.stock = stock;
}
}
MainActivity.java
(我省略了onCreate()
后面的class下面不相关的部分)
public class MainActivity extends AppCompatActivity {
private DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference().child("users").child("user1");
private ListView mListView;
private TextView tv_make;
private TextView tv_model;
private TextView tv_stock;
private ArrayList<String> list = new ArrayList<>();
private ArrayAdapter<String> adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
tv_make = (TextView) findViewById(R.id.tv_list_item_make);
tv_model = (TextView) findViewById(R.id.tv_list_item_model);
tv_stock = (TextView) findViewById(R.id.tv_list_item_stock);
databaseReference.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
String value = snapshot.child("make").getValue(String.class);
list.add(value);
mListView = (ListView) findViewById(R.id.lv_searches);
adapter = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_list_item_1, list);
mListView.setAdapter(adapter);
}
@Override
public void onChildChanged(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
}
@Override
public void onChildRemoved(@NonNull DataSnapshot snapshot) {
}
@Override
public void onChildMoved(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
}
});
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
这里是 content.main.xml
中的 ListView
:
<ListView
android:id="@+id/lv_searches"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
这里是 list_item.xml
,它应该位于我的 ListView 中。这是我想在 SearchModel.java
.
实例中显示三个字符串值(品牌、型号、库存)的地方
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="100dp"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:padding="10dp">
<TextView
android:id="@+id/tv_list_item_make"
android:layout_width="wrap_content"
android:layout_height="50dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_list_item_model"
android:layout_width="wrap_content"
android:layout_height="40dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
<TextView
android:id="@+id/tv_list_item_stock"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
这是我的 firebase 数据库布局:
被卡住了两天后,我终于可以回答我自己的问题了!希望这将帮助未来的初学者坚持尝试在 ArrayAdapter 中显示自定义视图。基本上,我创建了一个自定义 ArrayAdapter
class,其中可以容纳三个 TextViews
。
我绝不是专家,无法像其他人那样解释这一点,因此,我将 link 粘贴到我遵循并取得成功的两个视频教程中。
Android 初学者教程 #8 - 用于显示多列的自定义 ListView 适配器
https://www.youtube.com/watch?v=E6vE8fqQPTE&t=392s
Android 初学者教程 #9 - 自定义 ListView 适配器 [带加载动画]
https://www.youtube.com/watch?v=SApBLHIpH8A
下面是我更新的代码:
CustomAdapter.java
public class CustomAdapter extends BaseAdapter {
private static ArrayList<SearchModel> searchArrayList;
private LayoutInflater mInflater;
private Context mContext;
private int lastPosition;
/**
* Holds elements in a view
*/
static class ViewHolder {
TextView make;
TextView model;
TextView stock;
}
public CustomAdapter(Context context, ArrayList<SearchModel> results) {
searchArrayList = results;
mContext = context;
mInflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return searchArrayList.size();
}
@Override
public Object getItem(int position) {
return searchArrayList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
String make = searchArrayList.get(position).getMake();
String model = searchArrayList.get(position).getModel();
String stock = searchArrayList.get(position).getStock();
final View result;
ViewHolder holder;
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(mContext);
convertView = inflater.inflate(R.layout.list_item, parent, false);
holder = new ViewHolder();
holder.make = (TextView) convertView.findViewById(R.id.tv_list_item_make);
holder.model = (TextView) convertView.findViewById(R.id.tv_list_item_model);
holder.stock = (TextView) convertView.findViewById(R.id.tv_list_item_stock);
result = convertView;
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
result = convertView;
}
Animation animation = AnimationUtils.loadAnimation(mContext,
(position > lastPosition) ? R.anim.load_down_anim : R.anim.load_up_anim);
result.startAnimation(animation);
lastPosition = position;
holder.make.setText(make);
holder.model.setText(model);
holder.stock.setText(stock);
return convertView;
}
}
MainActivity.java
(仅onCreate
方法)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
databaseReference.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
String make = snapshot.child("make").getValue(String.class);
String model = snapshot.child("model").getValue(String.class);
String stock = snapshot.child("stock").getValue(Long.class).toString();
SearchModel searchModel = new SearchModel(make, model, stock);
searchList.add(searchModel);
CustomAdapter customAdapter = new CustomAdapter(getApplicationContext(), searchList);
mListView = (ListView) findViewById(R.id.lv_searches);
mListView.setAdapter(customAdapter);
}
@Override
public void onChildChanged(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
}
@Override
public void onChildRemoved(@NonNull DataSnapshot snapshot) {
}
@Override
public void onChildMoved(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
}
});
我花了大半天的时间试图弄清楚如何从我的 firebase 数据库中读取数据并通过 ArrayAdapter
在 ListView
中显示多个字段。终于让我的 ListView 在一个文本视图中显示一条数据后,我无法尝试显示其他两个字段。
在我的 MainActivity
class 中,我在 Adapter 构造函数中使用了 android.R.layout.simple_list_item_1
,因为我被告知 textViewResourceID 参数必须只包含一个 TextView。所以重申我的问题:我无法弄清楚如何使用数组适配器显示多个字段。此应用目前仅显示 make 字段。非常感谢,我大约一周前才开始 android 开发!下面是我的代码:
SearchModel.java
public class SearchModel {
public String make;
private String model;
private String stock;
public SearchModel() {}
public String getMake() {
return this.make;
}
public void setMake(String make) {
this.make = make;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getStock() {
return stock;
}
public void setStock(String stock) {
this.stock = stock;
}
}
MainActivity.java
(我省略了onCreate()
后面的class下面不相关的部分)
public class MainActivity extends AppCompatActivity {
private DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference().child("users").child("user1");
private ListView mListView;
private TextView tv_make;
private TextView tv_model;
private TextView tv_stock;
private ArrayList<String> list = new ArrayList<>();
private ArrayAdapter<String> adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
tv_make = (TextView) findViewById(R.id.tv_list_item_make);
tv_model = (TextView) findViewById(R.id.tv_list_item_model);
tv_stock = (TextView) findViewById(R.id.tv_list_item_stock);
databaseReference.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
String value = snapshot.child("make").getValue(String.class);
list.add(value);
mListView = (ListView) findViewById(R.id.lv_searches);
adapter = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_list_item_1, list);
mListView.setAdapter(adapter);
}
@Override
public void onChildChanged(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
}
@Override
public void onChildRemoved(@NonNull DataSnapshot snapshot) {
}
@Override
public void onChildMoved(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
}
});
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
这里是 content.main.xml
中的 ListView
:
<ListView
android:id="@+id/lv_searches"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
这里是 list_item.xml
,它应该位于我的 ListView 中。这是我想在 SearchModel.java
.
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="100dp"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:padding="10dp">
<TextView
android:id="@+id/tv_list_item_make"
android:layout_width="wrap_content"
android:layout_height="50dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_list_item_model"
android:layout_width="wrap_content"
android:layout_height="40dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
<TextView
android:id="@+id/tv_list_item_stock"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
这是我的 firebase 数据库布局:
被卡住了两天后,我终于可以回答我自己的问题了!希望这将帮助未来的初学者坚持尝试在 ArrayAdapter 中显示自定义视图。基本上,我创建了一个自定义 ArrayAdapter
class,其中可以容纳三个 TextViews
。
我绝不是专家,无法像其他人那样解释这一点,因此,我将 link 粘贴到我遵循并取得成功的两个视频教程中。
Android 初学者教程 #8 - 用于显示多列的自定义 ListView 适配器 https://www.youtube.com/watch?v=E6vE8fqQPTE&t=392s
Android 初学者教程 #9 - 自定义 ListView 适配器 [带加载动画] https://www.youtube.com/watch?v=SApBLHIpH8A
下面是我更新的代码:
CustomAdapter.java
public class CustomAdapter extends BaseAdapter {
private static ArrayList<SearchModel> searchArrayList;
private LayoutInflater mInflater;
private Context mContext;
private int lastPosition;
/**
* Holds elements in a view
*/
static class ViewHolder {
TextView make;
TextView model;
TextView stock;
}
public CustomAdapter(Context context, ArrayList<SearchModel> results) {
searchArrayList = results;
mContext = context;
mInflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return searchArrayList.size();
}
@Override
public Object getItem(int position) {
return searchArrayList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
String make = searchArrayList.get(position).getMake();
String model = searchArrayList.get(position).getModel();
String stock = searchArrayList.get(position).getStock();
final View result;
ViewHolder holder;
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(mContext);
convertView = inflater.inflate(R.layout.list_item, parent, false);
holder = new ViewHolder();
holder.make = (TextView) convertView.findViewById(R.id.tv_list_item_make);
holder.model = (TextView) convertView.findViewById(R.id.tv_list_item_model);
holder.stock = (TextView) convertView.findViewById(R.id.tv_list_item_stock);
result = convertView;
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
result = convertView;
}
Animation animation = AnimationUtils.loadAnimation(mContext,
(position > lastPosition) ? R.anim.load_down_anim : R.anim.load_up_anim);
result.startAnimation(animation);
lastPosition = position;
holder.make.setText(make);
holder.model.setText(model);
holder.stock.setText(stock);
return convertView;
}
}
MainActivity.java
(仅onCreate
方法)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
databaseReference.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
String make = snapshot.child("make").getValue(String.class);
String model = snapshot.child("model").getValue(String.class);
String stock = snapshot.child("stock").getValue(Long.class).toString();
SearchModel searchModel = new SearchModel(make, model, stock);
searchList.add(searchModel);
CustomAdapter customAdapter = new CustomAdapter(getApplicationContext(), searchList);
mListView = (ListView) findViewById(R.id.lv_searches);
mListView.setAdapter(customAdapter);
}
@Override
public void onChildChanged(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
}
@Override
public void onChildRemoved(@NonNull DataSnapshot snapshot) {
}
@Override
public void onChildMoved(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
}
});