具有自定义ArrayAdapter和Firestore的Android AutoComplete TextView无法正常工作

时间:2020-07-21 08:18:52

标签: android autocompletetextview

我想要做的是用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”));; ,整个工作正常。我想不出任何解决方案,所以在这里问。谢谢。

1 个答案:

答案 0 :(得分:0)

您正在处理网络请求,它不是顺序的。含义-在创建适配器并将其设置为auto对象时,返回歌曲列表的网络请求尚未完成。也许成功完成了,或者失败了-没有人知道。

因此,必须确保从OnCompleteListener更新歌曲列表和适配器。从onComplete方法更新列表时-您的适配器对该更新一无所知。它本身不会监视数组中的更改。

您必须做一些事情:

  1. 网络请求完成后-确保活动未完成。否则,您可能会导致应用程序崩溃(很难调试);
  2. 确保您将歌曲列表中的更改通知适配器。
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
    }
    
    ...

}