【发布时间】:2014-10-22 01:13:02
【问题描述】:
在开始之前,我检查了 Stackoverflow.com 中的所有其他答案。 很抱歉提出另一个相同的旧 notifyDataSetChanged() - 不起作用。
如果我找到答案,我会回答我自己的问题。
您好,我在使用扩展 BaseAdapter 的 ListViewAdapter 时遇到困难,如下所示。 在 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 中删除数组列表的原因。
更新是在 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;
}
}
【问题讨论】:
-
你可以尝试不调用 setSelection() 吗?
-
如果解决了问题,请在 Runnable 中发布 setSelection()。
-
亲爱的 svenoaks,让我研究一下您的建议并稍后添加评论。谢谢。