我想要做的是用Firestore中的数据填充AutoComplete TextView。我试图从Firestore检索数据,并使用它来创建Songs对象并将其存储在名为songs的ArrayList中。这些数据都是字符串。您可以在下面看到。 auto是指自动完成TextView。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
seekbar = findViewById(R.id.seekBar);
auto = findViewById(R.id.auto);
current = findViewById(R.id.start);
end = findViewById(R.id.end);
lol.add("chey");
lol.add("oi");
db.collection("Songs_names").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
if(task.isSuccessful()){
if (task.getResult() != null) {
for (QueryDocumentSnapshot document : task.getResult()) {
Log.d("tag","msg " + document.getString("name"));
songs.add(new Songs(document.getString("name")));
Log.d("show objects","showed" + songs);
}
}
}
}
});
songs_auto_adapter auto_adapter = new songs_auto_adapter(this,songs,this);
Log.d("show songs","show" + songs);
//ArrayAdapter<String> adapter = new ArrayAdapter<>(this,android.R.layout.simple_list_item_1,lol);
auto.setAdapter(auto_adapter);
然后,我将Adapter设置为auto_adapter。您可以在下面看到它。
public class songs_auto_adapter extends ArrayAdapter<Songs> {
private List<Songs> songsFull;
private Touch touch;
public songs_auto_adapter(@NonNull Context context, @NonNull List<Songs> objects,Touch touch) {
super(context,0, objects);
songsFull = new ArrayList<>(objects);
this.touch = touch;
}
@NonNull
@Override
public Filter getFilter() {
return filter;
}
@NonNull
@Override
public View getView(final int position, @Nullable View convertView, @NonNull ViewGroup parent) {
Log.d("View", "Creating Views");
if (convertView == null){
convertView = LayoutInflater.from(getContext()).inflate(R.layout.songs_for_auto,parent,false);
}
final TextView textView = convertView.findViewById(R.id.auto_text);
Songs songs = getItem(position);
if (songs != null) {
textView.setText(songs.getName());
}
convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("clicked","It works" + position);
touch.Touched(textView.getText().toString().trim());
}
});
return convertView;
}
private Filter filter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
List<Songs> suggestions = new ArrayList<>();
if ( constraint == null || constraint.length() == 0){
suggestions.addAll(songsFull);
}
else{
String filtertxt = constraint.toString().toLowerCase().trim();
for (Songs s : songsFull){
if (s.getName().toLowerCase().contains(filtertxt)){
suggestions.add(s);
Log.d("filtering","msg" + suggestions);
}
}
}
results.values = suggestions;
results.count = suggestions.size();
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
clear();
addAll((List) results.values);
notifyDataSetChanged();
Log.d("published","mmm" + results.values + songsFull);
}
};
问题是当我在AutoComplete TextView中键入内容时,什么都没有显示。然后,我使用Log.d,发现publishResult是首先被调用的那个,而从未调用performFiltering。请参阅下面的消息。
D/published: mmm[][]
I/zygote: Do partial code cache collection, code=55KB, data=53KB
After code cache collection, code=55KB, data=53KB
Increasing code cache capacity to 256KB
但是,当我像这样手动输入数据时,songs.add(new Songs(“ sth”));; ,整个工作正常。我想不出任何解决方案,所以在这里问。谢谢。
答案 0 :(得分:0)
您正在处理网络请求,它不是顺序的。含义-在创建适配器并将其设置为auto
对象时,返回歌曲列表的网络请求尚未完成。也许成功完成了,或者失败了-没有人知道。
因此,必须确保从OnCompleteListener
更新歌曲列表和适配器。从onComplete
方法更新列表时-您的适配器对该更新一无所知。它本身不会监视数组中的更改。
您必须做一些事情:
db.collection("Songs_names").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
// Step 1: if activity is no longer valid to use just skip this "task" response.
if (isFinishing() || isDestroyed()) return;
if(task.isSuccessful()){
if (task.getResult() != null) {
for (QueryDocumentSnapshot document : task.getResult()) {
Log.d("tag","msg " + document.getString("name"));
songs.add(new Songs(document.getString("name")));
Log.d("show objects","showed" + songs);
// Step 2: songs are updated
adapter.updateList(songs);
}
}
}
}
});
现在,您需要稍微修改一下适配器。添加了一个新方法,该方法可以接受歌曲列表并通知适配器有关更改。
public class songs_auto_adapter extends ArrayAdapter<Songs> {
private List<Songs> songsFull;
private Touch touch;
public songs_auto_adapter(@NonNull Context context, @NonNull List<Songs> objects,Touch touch) {
super(context,0, objects);
songsFull = new ArrayList<>(objects);
this.touch = touch;
}
public void updateList(@NonNull List<Songs> newList) {
songsFull = new ArrayList<>(newList);
clear();
addAll(songsFull); // Adapter is now aware of the updated list
}
...
}