我正在尝试在我的自定义适配器上调用notifyDataSetChanged()
,但它似乎无法正常工作。
这是我的活动: -
public class ThreadData extends ListActivity
{
private static final Uri SMS_URI = Uri.parse("content://sms");
HashMap<Long, BodyType> bodies = new HashMap<Long, BodyType>();
private String name, number;
private ListView listView;
private Activity activity;
ThreadDataAdapter adapter;
Handler handler;
private Context context;
private static final String PHONE_NUMBER_SEPARATORS = " ()-./";
static HashMap<String, ContactInfo.ContactDetail> info = new HashMap<String, ContactInfo.ContactDetail>();
public void onCreate(Bundle bundle)
{
super.onCreate(bundle);
setContentView(R.layout.chats);
Bundle extras = getIntent().getExtras();
activity = this;
context = this;
if(extras != null)
{
number = extras.getString("address");
ContactInfo.ContactDetail nameInfo = getContactsDetailWithNumber(number);
if(nameInfo != null)
{
name = nameInfo.name;
}
else
{
name = number;
}
}
TextView person = (TextView) findViewById(R.id.chat_person);
person.setText(name);
ImageButton callPerson = (ImageButton) findViewById(R.id.call_person);
callPerson.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
popUpDialerAlert();
}
});
buildMessageList();
ArrayList<BodyType> items = sortBodies();
adapter = new ThreadDataAdapter(this, items);
listView = getListView();
listView.setAdapter(adapter);
listView.setStackFromBottom(true);
getContentResolver().registerContentObserver(SMS_URI, true, new MyContentObserver(handler));
}
public void buildMessageList()
{
Cursor cursor = getContentResolver().query(SMS_URI, null, null, null, "date ASC");
startManagingCursor(cursor);
while (cursor.moveToNext())
{
BodyType bodyInfo = new BodyType();
String address = cursor.getString(cursor.getColumnIndex("address"));
bodyInfo.body = cursor.getString(cursor.getColumnIndexOrThrow("body"));
Long date = cursor.getLong(cursor.getColumnIndexOrThrow("date"));
bodyInfo.date = date;
String type = cursor.getString(cursor.getColumnIndexOrThrow("type"));
if(type.equals("1"))
{
bodyInfo.type = "received";
}
else if(type.equals("2"))
{
bodyInfo.type = "sent";
}
else if(type.equals("3"))
{
bodyInfo.type = "draft";
}
String number = filterPhoneNumber(address);
ContactInfo.ContactDetail nameInfo = getContactsDetailWithNumber(number);
String personName = number;
if(nameInfo != null)
{
personName = nameInfo.name;
}
else
{
personName = number;
}
if(personName.equals(name))
{
bodies.put(date, bodyInfo);
}
}
}
public void popUpDialerAlert()
{
AlertDialog.Builder dialerAlert = new AlertDialog.Builder(this);
dialerAlert.setTitle("Confirm");
dialerAlert.setMessage("Call" + " " + name + "?");
dialerAlert.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogInterface, int i) {
Uri uri = Uri.parse("tel:" + number);
Intent intent = new Intent((Intent.ACTION_CALL));
intent.setData(uri);
context.startActivity(intent);
}
});
dialerAlert.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogInterface, int i) {
}
});
dialerAlert.show();
}
public ArrayList<BodyType> sortBodies()
{
ArrayList<Long> dates = new ArrayList<Long>(bodies.keySet());
Collections.sort(dates);
ArrayList<BodyType> items = new ArrayList<BodyType>();
for(Long date : dates)
{
for(Long key : bodies.keySet())
{
if(date.equals(key))
{
items.add(bodies.get(key));
}
}
}
return items;
}
public void printBodies(ArrayList<BodyType> items)
{
for(BodyType bodyType : items)
{
log(bodyType.date.toString());
log(bodyType.body);
log(bodyType.type);
}
}
static class BodyType
{
public String type;
public String body;
public Long date;
}
public static ContactInfo.ContactDetail getContactsDetailWithNumber(String number)
{
if(info.containsKey(number))
{
return info.get(number);
}
return null;
}
public static String filterPhoneNumber(String phoneNumber)
{
if (phoneNumber == null)
{
return null;
}
int length = phoneNumber.length();
StringBuilder builder = new StringBuilder(length);
for (int i = 0; i < length; i++)
{
char character = phoneNumber.charAt(i);
if (PHONE_NUMBER_SEPARATORS.indexOf(character) == -1)
{
builder.append(character);
}
}
return builder.toString();
}
public class MyContentObserver extends ContentObserver
{
public MyContentObserver(Handler handler)
{
super(handler);
}
@Override
public void onChange(boolean selfChange)
{
buildMessageList();
adapter.notifyDataSetChanged();
super.onChange(selfChange);
}
}
public void log(String msg)
{
Log.e("ThreadData", msg);
}
}
这是我的自定义适配器: -
public class ThreadDataAdapter extends BaseAdapter
{
Activity activity;
ArrayList<ThreadData.BodyType> data;
LayoutInflater inflater;
public ThreadDataAdapter(Activity a, ArrayList<ThreadData.BodyType> list)
{
activity = a;
data = list;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
return data.size(); //To change body of implemented methods use File | Settings | File Templates.
}
public Object getItem(int i) {
return data.get(i); //To change body of implemented methods use File | Settings | File Templates.
}
public long getItemId(int i) {
return i; //To change body of implemented methods use File | Settings | File Templates.
}
public static class ViewHolder
{
public TextView message;
}
public View getView(int i, View view, ViewGroup viewGroup)
{
View row = view;
final ViewHolder holder;
ThreadData.BodyType bodyInfo = data.get(i);
if(bodyInfo.type.equals("sent"))
{
Log.e("MMS", bodyInfo.body);
row = inflater.inflate(R.layout.sentitem, viewGroup, false);
holder = new ViewHolder();
holder.message = (TextView)row.findViewById(R.id.sent);
holder.message.setText(bodyInfo.body);
}
else
{
row = inflater.inflate(R.layout.chatitems, viewGroup, false);
holder = new ViewHolder();
holder.message = (TextView)row.findViewById(R.id.received);
holder.message.setText(bodyInfo.body);
}
return row;
}
@Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
}
}
我想要做的是,只要设备的SMS数据库发生变化,我就会在ContentObserver
注册notifyDataSetChanged(
并呼叫onChange()
)。但它根本不起作用。
任何帮助将不胜感激。请帮忙!
提前致谢。
答案 0 :(得分:5)
您在适配器中使用的List
(数据)是您在sortBodies中创建的List
的引用。永远不会更新。因此,您的适配器卡在未使用OnChange
方法更新的项目副本上。
换句话说,无论是否调用OnChange
,getView将始终返回相同的视图...
您的适配器应使用实体,因为此MashMap已由您的OnChange
方法更新。