Android BaseAdapter notifyDataSetChanged()有时会起作用,有时也不起作用

时间:2014-10-22 01:13:02

标签: android listview

在开始之前,我检查了Stackoverflow.com中的所有其他答案。 很抱歉打开另一个旧的notifyDataSetChanged() - 没有工作的东西。

如果我找到答案,我会回答我自己的问题。

嗨,我很难使用ListViewAdapter扩展BaseAdapter,如下所示。 在Stackoverflow.com或许多其他博客中,有很多关于这个问题的讨论。 解决方案似乎趋同于说

1)不要忘记设置setListAdapter。 2)添加新数据时使用notifyDataSetChanged()。 (有人说使用notifyDataSetInvalidate ...)

我一直在研究的教程是

http://adilsoomro.blogspot.kr/2012/12/android-listview-with-speech-bubble.html

问题是有时候效果很好,但有时却没有。

没有模式。

由于消息是从其他系统传输的,我认为这是由于网络问题。 但所有的消息都无缝地进入我的应用程序。

我没有在ListViewActivity上使用ArrayList实例的原因是 从某些系统操作点发生一个ArrayList实例的情况 ListViewAdapter中的内容无法与ListViewActivity上的arrayList同步。 而且我已经证实,那里开始存在一个时刻 一些消息被放入列表A(ListViewActivty内)和其他消息中 列表B(在ListViewAdapter中,但我不确定是否真的如此)。 这就是我删除ListViewActivty中的arraylist的原因。

更新在AsyncTask的onPostExecute部分内完成,而不是使用runUiThread (使用runUiThread并没有区别。)

我发现当列表视图没有更新时,getView()也没有被调用, 即使适配器中的消息列表已添加数据并且getCount()返回 准确的刷新数据大小。

我怀疑onPostExecute中的操作偶尔会被阻止 一些未知的过程。

当我在我的应用上发布UI事件(例如,输入文本)时, 它会对屏幕上添加的数据进行后期刷新 在调用addNewMessage()时已经完成了。

=============================================== ========================

1。调用addNewMessage()的AsycTask(ListViewActivity.java的一部分)

private class RefreshListView extends AsyncTask<Argument, String, Argument>
{
@Override
protected Argument doInBackground(Argument... _args) 
{ 
     Argument result = new Argument();

     result.setMessageString( _args[0].getMessageString() );
     result.setIsMine( _args[0].getIsMine() );

     return result;
}

      @Override
public void onProgressUpdate(String... v) 
{ 

}

@Override
protected void onPostExecute(Argument _arg ) 
{
    addNewMessage(new Message( _arg.getMessageString(), _arg.getIsMine() ) );  
}
} 

=============================================== ========================

2。调用notifyDataSetChanged()的点。 (ListViewActivity.java的一部分)

public void addNewMessage( final Message _message )
{
    adapter.add( _message ); 
    adapter.notifyDataSetChanged();
    getListView().setSelection( adapter.observeMessageList().size() - 1 );
}

=============================================== ========================

3。 ListViewActivity将ListViewAdapter设置为观察者

public void onCreate( Bundle savedInstanceState ) 
{
    adapter = new ListViewAdapter( this );
    this.setListAdapter( adapter );
}

=============================================== ========================

4。 ListViewAdapter.java,它具有存储数据项

的实际arrayList
import java.util.ArrayList;
import java.util.Iterator;

import com.test.R;

import android.content.Context;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;

// http://stackoverflow.com/questions/3669325/notifydatasetchanged-example
public class ListViewAdapter extends BaseAdapter
{
private Context mContext;

public static ArrayList<com.test.Message> mMessages = new ArrayList<com.test.Message>();

public ListViewAdapter(Context context ) 
{
     super();

     this.mContext = context;
}

public void clearMessages()
{
    ListViewAdapter.mMessages.clear();
}

public void add( Message  _message )
{
    ListViewAdapter.mMessages.add( _message );
}

public ArrayList<com.test.Message> observeMessageList()
{
     return ListViewAdapter.mMessages;
}

@Override
public int getCount() 
{ 
    return mMessages.size();
} 


@Override
public Object getItem( int position ) 
{       
    return mMessages.get( position );
}


@Override
public View getView( int position, View convertView, ViewGroup parent ) 
{
    com.test.Message message = (com.test.Message) this.getItem(position);

    ViewHolder holder; 

    if ( convertView == null )
    {
        holder = new ViewHolder();

        convertView = LayoutInflater.from(mContext).inflate(R.layout.sms_row, parent, false);

        holder.message = (TextView) convertView.findViewById(R.id.message_text);

        convertView.setTag(holder);
    }
    else
    {
        holder = (ViewHolder) convertView.getTag();
    }

    holder.message.setText( message.getMessage() );

    LayoutParams lp = (LayoutParams) holder.message.getLayoutParams();

    // check if it is a status message then remove background, and change text color.
    if ( message.isStatusMessage() )
    {
        holder.message.setBackgroundDrawable(null);

        lp.gravity = Gravity.LEFT;

        // holder.message.setTextColor( R.color.textFieldColor );
    }
    else
    {       
        // Check whether message is mine to show green background and align to right
        if ( message.isMine() )
        {
            holder.message.setBackgroundResource(R.drawable.speech_bubble_green);
            lp.gravity = Gravity.RIGHT;
        }
        // If not mine then it is from sender to show orange background and align to left
        else
        {
            holder.message.setBackgroundResource(R.drawable.speech_bubble_orange);
            lp.gravity = Gravity.LEFT;
        }

        holder.message.setLayoutParams(lp);

        // holder.message.setTextColor( R.color.textColor );    
    }

    return convertView;
}

public static class ViewHolder
{
    TextView message;
}

@Override
// http://stackoverflow.com/questions/6711592/what-is-the-intent-of-the-methods-getitem-and-getitemid-in-the-android-class-bas
public long getItemId(int position) 
{
    // Unimplemented, because we aren't using Sqlite.

    // http://stackoverflow.com/questions/24223393/android-listview-custom-adapter-getview-never-called-up
    return 0;
    // return position;
}

}

1 个答案:

答案 0 :(得分:0)

这不是处理这个问题的一种认证方式。

但是目前我已经通过添加以下方法做了一些解决方法。 这在每1秒内在一些单独的线程中调用。 因此无论实际是否添加了新数据,都只是 做notifyDataSetChanged(),如果真的有一些项目添加但是 如上所述,无法在UI上看到它,它将在用户屏幕上刷新。

public void refresh()
{
     this.runOnUiThread
     ( 
        new Runnable() 
        { 
            @Override 
            public void run() 
            { 
                  adapter.notifyDataSetChanged();

                  getListView().setSelection( adapter.observeMessageList().size() - 1 );
            } 
     });  
}

如果我找到一些根本原因,我会详细说明这个问题。