在 notifyDataSetChanged 上未调用 GetView,ListView 卡住
Posted
技术标签:
【中文标题】在 notifyDataSetChanged 上未调用 GetView,ListView 卡住【英文标题】:GetView not called on notifyDataSetChanged, ListView is stuck 【发布时间】:2021-04-20 21:25:32 【问题描述】:我有一个问题,我已经创建了自定义适配器,在联系人应用程序中对联系人对象进行自定义过滤,它可以很好地过滤联系人姓名,并且过滤后的联系人列表被正确保存。问题是当我在 searchView 中键入任何内容时,找到的行数是正确的,但有关找到的行的信息不正确。问题似乎与适配器中的 getView 函数有关,它不应该被调用。例如,如果我有三个联系人:“abc”、“aaa”、“aba”,并且它们按从上到下的顺序显示在开头,那么如果我在 searchView 中键入“ab”,那么它会找到 2 行,但它们仍然和开始时一样,它们应该是“abc”和“aba”,但它们是“abc”和“aaa”。适配器创建的第一个视图似乎由于某种原因被卡住了。
我的活动课:
package com.example.androidlab;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.Toast;
import java.lang.reflect.Type;
import java.util.ArrayList;
public class AllContactsActivity extends AppCompatActivity
static ArrayList<Contact> contacts = new ArrayList<>();
ContactsAdapter contactsAdapter;
ListView listView;
SearchView searchView;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_all_contacts);
FloatingActionButton addContact = findViewById(R.id.newContact);
listView = findViewById(R.id.allContactsList);
searchView = findViewById(R.id.searchContacts);
SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences("com.tanay.thunderbird.contacts", Context.MODE_PRIVATE);
Gson gson = new Gson();
String json = sharedPreferences.getString("contacts", null);
Type type = new TypeToken<ArrayList<Contact>>()
.getType();
contacts = gson.fromJson(json, type);
if (contacts == null)
contacts = new ArrayList<>();
if (contacts.size() == 0)
Toast.makeText(this, "There are no contacts.", Toast.LENGTH_LONG).show();
contactsAdapter = new ContactsAdapter(this, contacts);
listView.setAdapter(contactsAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener()
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
Intent intent = new Intent(getApplicationContext(), EditContactActivity.class);
intent.putExtra("noteID", position);
startActivity(intent);
finish();
);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener()
@Override
public boolean onQueryTextSubmit(String query)
contactsAdapter.getFilter().filter(query);
return false;
@Override
public boolean onQueryTextChange(String query)
contactsAdapter.getFilter().filter(query);
return false;
);
addContact.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
Intent intent = new Intent(getApplicationContext(), NewContactActivity.class);
startActivity(intent);
finish();
);
@Override
public void onBackPressed()
finish();
我的适配器类:
package com.example.androidlab;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Base64;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class ContactsAdapter extends BaseAdapter implements Filterable
Context context;
List<Contact> contacts;
List<Contact> filteredContacts;
ContactFilter mFilter = new ContactFilter();
String filterString;
ContactsAdapter(Context context, List<Contact> contacts)
this.context = context;
this.contacts = contacts;
filteredContacts = contacts;
@Override
public int getCount()
if(contacts.size() != filteredContacts.size() || filterString != null)
return filteredContacts.size();
else
filteredContacts = contacts;
return contacts.size();
@Override
public Object getItem(int position)
return contacts.get(position);
@Override
public long getItemId(int position)
return contacts.indexOf(getItem(position));
@Override
public Filter getFilter()
return mFilter;
private class ViewHolder
ImageView imageView;
TextView name;
TextView phoneNumber;
@Override
public View getView(int position, View convertView, ViewGroup parent)
ViewHolder holder = null;
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(AllContactsActivity.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = mInflater.inflate(R.layout.list_contacts, null);
holder = new ViewHolder();
holder.name = (TextView) convertView.findViewById(R.id.contactName);
holder.imageView = (ImageView) convertView.findViewById(R.id.imageOfContact);
holder.phoneNumber = (TextView) convertView.findViewById(R.id.phoneNumber);
Contact contact;
if(filteredContacts.size() != contacts.size()) contact = filteredContacts.get(position);
else contact = contacts.get(position);
if (contact.getAvatar() == null)
if (contact.getGender() == true)
holder.imageView.setImageResource(R.drawable.ic_man);
else holder.imageView.setImageResource(R.drawable.ic_woman);
else
byte[] decodedString = Base64.decode(contact.getAvatar(), Base64.DEFAULT);
Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
holder.imageView.setImageBitmap(decodedByte);
holder.name.setText(contact.getName());
holder.phoneNumber.setText(String.valueOf(contact.getPhoneNumber()));
return convertView;
private class ContactFilter extends Filter
@Override
protected FilterResults performFiltering(CharSequence constraint)
filterString = constraint.toString().toLowerCase();
FilterResults results = new FilterResults();
final List<Contact> list = contacts;
int count = list.size();
final ArrayList<Contact> nList = new ArrayList<Contact>();
for (int i = 0; i < count; i++)
if(contacts.get(i).getName().contains(filterString)) nList.add(contacts.get(i));
results.values = nList;
results.count = nList.size();
return results;
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results)
filteredContacts = (ArrayList<Contact>) results.values;
notifyDataSetChanged();
编辑:我摆脱了 getView 函数中的 if(contentView == null) 并且一切正常
【问题讨论】:
【参考方案1】:检查convertView == null
应该只处理你的View
的膨胀和创建一个新的ViewHolder
其余的getView
代码应该始终运行。
public View getView(int position, View convertView, ViewGroup parent)
ViewHolder holder;
if (convertView == null)
convertView = mInflater.inflate(R.layout.list_contacts, null);
// attach a new holder to the inflated view
holder = new ViewHolder();
convertView.setTag(holder);
else
// get an existing holder from the existing view
holder = (ViewHolder) convertView.getTag();
// update your holder here:
// e.g. holder.name.setText(contact.getName());
return convertView;
【讨论】:
以上是关于在 notifyDataSetChanged 上未调用 GetView,ListView 卡住的主要内容,如果未能解决你的问题,请参考以下文章
在 customAdapter.notifyDataSetChanged 之后 ListView 不更新
[完成]notifyDataSetChanged() 不会自动更新 ListActivity
在 notifyDataSetChanged 后 Android ListView 不刷新
ArrayAdapter.NotifyDataSetChanged() 不工作?