安卓:notifyDataSetChanged();不工作
Posted
技术标签:
【中文标题】安卓:notifyDataSetChanged();不工作【英文标题】:Android: notifyDataSetChanged(); not working 【发布时间】:2013-04-16 10:53:41 【问题描述】:我在服务器中有一个数据库,我从平板电脑中从数据库中的一个表中获取一些值。我将此信息正确加载到列表中,但我想知道为什么当发生更改时,即使我使用notifyDataSetChanged();
也没有任何反应。我必须说,要加载加载数据,请使用 AsyncTaskClass
所以,我的问题是我不知道是否使用 notifyDataSetChanged();方法正确,因为如果有变化我想刷新图像。以下是该类的部分代码:
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.all_candidatos);
candidatosList = new ArrayList<HashMap<String, String>>();
new CargarCandidatos().execute();
// public void timer()
// new CountDownTimer(tiempo, 100)
//
// public void onTick(long millisUntilFinished)
//
//
//
// public void onFinish()
// // new CargarCandidatos().execute();
//
//
// .start();
/**
* Background Async Task to Load all product by making HTTP Request
* */
class CargarCandidatos extends AsyncTask<String, String, String>
/**
* Before starting background thread Show Progress Dialog
* */
@Override
protected void onPreExecute()
super.onPreExecute();
pDialog = new ProgressDialog(Monitorizacion.this);
pDialog.setMessage("Loading ...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
/**
* getting All products from url
* */
protected String doInBackground(String... args)
List<NameValuePair> params = new ArrayList<NameValuePair>();
JSONObject json = jParser.makeHttpRequest(url_candidatos, "GET", params);
Log.d("Candidatos: ", json.toString());
try
int success = json.getInt(TAG_SUCCESS);
if (success == 1)
candidatos = json.getJSONArray(TAG_CANDIDATOS);
for (int i = 0; i < candidatos.length(); i++)
JSONObject c = candidatos.getJSONObject(i);
// Storing each json item in variable
String nserie = c.getString(TAG_NSERIE);
String dni = c.getString(TAG_DNI);
String nombre = c.getString(TAG_NOMBRE);
String test = c.getString(TAG_TEST);
String pregunta = c.getString(TAG_PREGUNTA);
String bateria = c.getString(TAG_BATERIA);
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
// adding each child node to HashMap key => value
map.put(TAG_NSERIE, nserie);
map.put(TAG_DNI, dni);
map.put(TAG_NOMBRE, nombre);
map.put(TAG_TEST, test);
map.put(TAG_PREGUNTA, pregunta);
map.put(TAG_BATERIA, bateria);
// adding HashList to ArrayList
candidatosList.add(map);
catch (JSONException e)
e.printStackTrace();
return null;
/**
* After completing background task Dismiss the progress dialog
* **/
protected void onPostExecute(String file_url)
pDialog.dismiss();
runOnUiThread(new Runnable()
public void run()
/**
* Updating parsed JSON data into ListView
* */
adapter = new SimpleAdapter(
Monitorizacion.this, candidatosList,
R.layout.list_item, new String[] TAG_NSERIE,
TAG_DNI, TAG_NOMBRE, TAG_TEST, TAG_PREGUNTA, TAG_BATERIA,
new int[] R.id.id, R.id.dni, R.id.nombre, R.id.test, R.id.pregunta, R.id.bateria);
setListAdapter(adapter);
adapter.notifyDataSetChanged();
// timer();
);
【问题讨论】:
任何崩溃?您不希望 runOnUIThread 简单地设置适配器。确保 candidatosList 有一些值。 嗨 Triode,我在屏幕上加载了所有数据库值,并且活动没有崩溃。问题是即使数据库得到更新,用户界面也不会用新值刷新。 @Katherine99 如果我的答案解决了您的问题,您可以将答案标记为已选。 :) 【参考方案1】:notifyDataSetChanged()
对您不起作用的主要原因之一是,
您的适配器丢失了对您列表的引用。
当您第一次初始化 Adapter
时,它会引用您的 arrayList
并将其传递给它的超类。但是,如果您重新初始化现有的 arrayList
,它会丢失引用,因此会丢失与 Adapter
的通信通道。
在创建新列表并将其添加到Adapter
时。始终遵循以下准则:
-
在全局声明
arrayList
时对其进行初始化。
直接将列表添加到适配器,而不检查空值和空值。直接将适配器设置到列表中(不检查任何条件)。适配器向您保证,无论您对arrayList
的数据进行更改,它都会处理它,但永远不会
失去参考。
始终修改 arrayList 本身中的数据(如果您的数据是全新的,那么您可以在实际将数据添加到列表之前调用 adapter.clear()
和 arrayList.clear()
)但不要设置适配器,即如果新数据是填充在arrayList
而不仅仅是adapter.notifyDataSetChanged()
忠于文档。
【讨论】:
非常感谢,我的问题是不信任适配器的功能。 非常感谢,通过您的解释,我对适配器和列表视图有了很多了解,也为我的许多疑问找到了解决方案。 如果数据集是游标,我如何实现相同的效果?我无法清除光标并再次添加所有项目。 您可以使用 CursorAdapter。请参阅github.com/codepath/android_guides/wiki/…。【参考方案2】:你需要编辑的是把你的
runOnUiThread(new Runnable()
public void run()
/**
* Updating parsed JSON data into ListView
* */
adapter = new SimpleAdapter(
Monitorizacion.this, candidatosList,
R.layout.list_item, new String[] TAG_NSERIE,
TAG_DNI, TAG_NOMBRE, TAG_TEST, TAG_PREGUNTA, TAG_BATERIA,
new int[] R.id.id, R.id.dni, R.id.nombre, R.id.test, R.id.pregunta, R.id.bateria);
setListAdapter(adapter);
adapter.notifyDataSetChanged();
// timer();
);
进入 OnCreate()。并从 Asynctask 返回列表 candidatosList。而不是设置用于更新candidatosList列表的计时器。
【讨论】:
抱歉,不刷新会继续 嗨,如果我使用 candidatosList.clear();当我运行活动时,列表视图不包含任何数据 请确保您在candidatosList
中的数据每次都会更新。如果和以前一样,你可以删除单个项目并设置adapter.notifyDataSetChanged();
,然后设置setListAdapter(adapter);
感谢添加 runOnUiThread(new Runnable()) 后对我有用; ,但想知道它是如何工作的?【参考方案3】:
如果您有一个空的 registerDataSetObserver()
覆盖,可能值得检查。 Android Studio 为我添加了一个,但没有实现对 super 的调用。如下添加它足以让我的 listView 再次工作:
@Override
public void registerDataSetObserver(DataSetObserver observer)
super.registerDataSetObserver(observer);
【讨论】:
【参考方案4】:适配器定义布局的组成部分! -> setListAdapter() : 为 ListView/GridView/Gallery 定义适配器... 但你需要指定数据!
我向你推荐,在“onCreate”或构造函数中初始化“setListAdapter”。 将数据设置到适配器后(例如:adapter.setItem(yourData))
现在!你应该调用 notifyDataSetChanged ! 因为您已更改数据但视图未刷新并且 notifydatasetchanged() 重新加载视图的内容(ListView/GridView/Gallery...)
为了获得良好的实践和正确理解,我建议您使用“baseAdapter”来使用“自定义适配器”
阅读并完成本教程(我已经学习过):http://www.androidhive.info/2012/02/android-custom-listview-with-image-and-text/
阅读文档:http://developer.android.com/reference/android/widget/BaseAdapter.html
【讨论】:
谢谢 anthony,我会阅读那些网页,然后告诉你结果【参考方案5】:应该从 UI 线程调用更新函数。 我的答案实际上与@user1621629 的answer 相似,不同之处在于我使用的是 rxJava,所以这里的工作代码可以为我解决这个问题:
this.subscriber = myAdapter.getSubscriber(); // keep for unsubscribe in destroy
dataSource.subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread()).subscribe(this.subscriber);
所以我设置所有执行以获取列表的数据到计算线程,但在 UI 线程中显示结果。
以下是我为此创建订阅者的方法:
public class MyListAdapter extends RecyclerView.Adapter<LocationListAdapter.ViewHolder>
private List<ListItem> mDataset = new ArrayList<>();
public Subscriber<ListItem[]> getSubscriber()
return Subscribers.create(new Action1<ListItem[]>()
@Override
public void call(ListItem[] listItems)
mDataset.clear();
mDataset.addAll(Arrays.asList(listItems));
notifyDataSetChanged();
);
......
【讨论】:
【参考方案6】:作为Hissain describes above,
您需要维护对列表的引用
这是我如何让它工作的:
让发送给适配器的列表设置为活动中的实例成员
在对数据执行更改的逻辑中,确保它更新 Activity 传递给适配器的相同列表实例
然后调用 .notifyDataSetChanged();工作过
记住 listView 的位置从 1 开始,所以你必须为你的 java.util.List 做 (listViewPosition - 1)
【讨论】:
【参考方案7】:我没有太多声誉可以评论 Hissain 先生的回答。这是正确的,但我想再提一件事,对列表的引用不应该改变。如果底层数据源发生变化,请不要更改对新列表的引用。只需对同一个列表对象执行操作。为此,请使用 clear() 清除列表,然后使用 add() 或 addALL() 将数据添加到同一列表中,然后调用 notifyDataSetChanged()。例如。 首次初始化列表时
list = dataSource.getList();
然后可以从列表中添加和删除内容并调用 notifyDataSetChanged() 它工作正常,但如果在代码中,尝试更改对另一个对象的引用。喜欢
list = dataSource.getList();
其中 getList() 每次都返回新列表,因此引用更改为其他列表对象,调用 notifyDataSetChnaged 不会对列表产生影响。但如果 getList() 返回相同的列表对象,则可以正常工作。
【讨论】:
【参考方案8】:如果您设置的一切正常但仍然无法正常工作,那么您的列表... 是不是列表中的 Mutablekind...!
private val demoList: MutableList<AnyClass> = mutableListOf()
一旦你像上面的可变方式定义了你的列表,那么你就可以获得方法
.add
.addAll
.remove
等等……
否则,如果您创建了普通列表,那么它将无法像 notifyDataSetChanged
那样工作
【讨论】:
以上是关于安卓:notifyDataSetChanged();不工作的主要内容,如果未能解决你的问题,请参考以下文章
android listview不能刷新 adapter.notifyDataSetChanged()和setListAdapter(myAdapter)都不好用
Android RecyclerView:notifyDataSetChanged() IllegalStateException
ArrayAdapter.NotifyDataSetChanged() 不工作?