Android-notifyDataSetChanged()在自定义适配器上不起作用? [英] Android - notifyDataSetChanged() not working on custom adapter?

查看:115
本文介绍了Android-notifyDataSetChanged()在自定义适配器上不起作用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在自定义适配器上调用 notifyDataSetChanged(),但似乎无法正常工作。

I am trying to call notifyDataSetChanged() on my custom adapter but it seems not to be working.

这是我的活动:-

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();  
}
}

我要注册的是 ContentObserver 并在 onChange() notifyDataSetChanged() >只要设备的SMS数据库有任何更改。

What i am trying to do is, i am registering a ContentObserver and calling notifyDataSetChanged() in its onChange() whenever there is some change in device's SMS database. But it isn't working at all.

任何帮助将不胜感激。

Any help would be appreciated. Please HELP!

请提前谢谢。

推荐答案

<$在适配器(数据)中使用的c $ c> List 是在sortBodies中创建的 List 的引用。它永远不会更新。因此,您的适配器会卡在 OnChange 方法未更新的项目副本上。

The List you use in your adapter (data) is a reference on a List that you create in sortBodies. It is never updated. Thus your adapter is stuck on a copy of items that is not updated by your OnChange method.

,无论是否调用 OnChange ,getView都将始终返回相同的视图...

In other words, whether or not OnChange is called, getView will always return the same views...

您的适配器应使用正文,因为此MashMap是通过您的 OnChange 方法更新的。

You adapter should use bodies, as this MashMap is updated by your OnChange method.

这篇关于Android-notifyDataSetChanged()在自定义适配器上不起作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆