Android - notifyDataSetChanged () не работает на пользовательском адаптере? - PullRequest
1 голос
/ 26 июня 2011

Я пытаюсь вызвать 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();  
}
}

Я пытаюсь сделать следующее: я регистрирую ContentObserver и вызываю notifyDataSetChanged() в его onChange() всякий раз, когда естьнекоторые изменения в базе данных SMS устройства.Но это не работает вообще.

Любая помощь будет оценена.ПОМОГИТЕ!

Заранее спасибо.

1 Ответ

5 голосов
/ 26 июня 2011

List, который вы используете в своем адаптере (данные), является ссылкой на List, который вы создаете в sortBodies.Это никогда не обновляется.Таким образом, ваш адаптер прикреплен к копии элементов, которая не обновляется вашим OnChange методом.

Другими словами, независимо от того, вызывается ли OnChange или нет, getView всегда будет возвращать одни и те же представления ...

Ваш адаптер должен использовать тела, так как этот MashMap обновляется вашим OnChange методом.

...