Le contenu de la carte a changé, mais ListView n'a pas reçu de notification Avec AsyncTask
Je suis en utilisant AsyncTask pour définir mes articles et d'autres choses, dans le postExecute j'appelle une Méthode synchronisée où je fais ce
mAllResultsAdapter.setItems(mAllResultsItem);
mAllResultsAdapter.notifyDataSetChanged();
mListView.invalidate();
mListView.requestLayout();
La plupart du temps si je télécharger de nouvelles données et de mettre à jour mon listview adaptateur/il fonctionne simplement, et très bon.
Mais de toute façon, il se bloque parfois, quelqu'un peut-il m'aider avec ce problème.
heres mon crash.
03-19 14:15:02.170: E/AndroidRuntime(23242): FATAL EXCEPTION: main
03-19 14:15:02.170: E/AndroidRuntime(23242): java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. [in ListView(2131034153, class android.widget.ListView) with Adapter(class com....tracebuzz.allresults.AllResultsAdapter)]
03-19 14:15:02.170: E/AndroidRuntime(23242): at android.widget.ListView.layoutChildren(ListView.java:1556)
03-19 14:15:02.170: E/AndroidRuntime(23242): at android.widget.AbsListView.onLayout(AbsListView.java:1993)
03-19 14:15:02.170: E/AndroidRuntime(23242): at android.view.View.layout(View.java:9606)
03-19 14:15:02.170: E/AndroidRuntime(23242): at android.view.ViewGroup.layout(ViewGroup.java:3879)
03-19 14:15:02.170: E/AndroidRuntime(23242): at android.widget.FrameLayout.onLayout(FrameLayout.java:400)
03-19 14:15:02.170: E/AndroidRuntime(23242): at android.view.View.layout(View.java:9606)
03-19 14:15:02.170: E/AndroidRuntime(23242): at android.view.ViewGroup.layout(ViewGroup.java:3879)
03-19 14:15:02.170: E/AndroidRuntime(23242): at android.widget.RelativeLayout.onLayout(RelativeLayout.java:912)
03-19 14:15:02.170: E/AndroidRuntime(23242): at android.view.View.layout(View.java:9606)
03-19 14:15:02.170: E/AndroidRuntime(23242): at android.view.ViewGroup.layout(ViewGroup.java:3879)
03-19 14:15:02.170: E/AndroidRuntime(23242): at android.widget.FrameLayout.onLayout(FrameLayout.java:400)
03-19 14:15:02.170: E/AndroidRuntime(23242): at android.view.View.layout(View.java:9606)
03-19 14:15:02.170: E/AndroidRuntime(23242): at android.view.ViewGroup.layout(ViewGroup.java:3879)
03-19 14:15:02.170: E/AndroidRuntime(23242): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1542)
03-19 14:15:02.170: E/AndroidRuntime(23242): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1403)
03-19 14:15:02.170: E/AndroidRuntime(23242): at android.widget.LinearLayout.onLayout(LinearLayout.java:1314)
03-19 14:15:02.170: E/AndroidRuntime(23242): at android.view.View.layout(View.java:9606)
03-19 14:15:02.170: E/AndroidRuntime(23242): at android.view.ViewGroup.layout(ViewGroup.java:3879)
03-19 14:15:02.170: E/AndroidRuntime(23242): at android.widget.FrameLayout.onLayout(FrameLayout.java:400)
03-19 14:15:02.170: E/AndroidRuntime(23242): at android.view.View.layout(View.java:9606)
03-19 14:15:02.170: E/AndroidRuntime(23242): at android.view.ViewGroup.layout(ViewGroup.java:3879)
03-19 14:15:02.170: E/AndroidRuntime(23242): at android.view.ViewRoot.performTraversals(ViewRoot.java:1288)
03-19 14:15:02.170: E/AndroidRuntime(23242): at android.view.ViewRoot.handleMessage(ViewRoot.java:2066)
03-19 14:15:02.170: E/AndroidRuntime(23242): at android.os.Handler.dispatchMessage(Handler.java:99)
03-19 14:15:02.170: E/AndroidRuntime(23242): at android.os.Looper.loop(Looper.java:132)
03-19 14:15:02.170: E/AndroidRuntime(23242): at android.app.ActivityThread.main(ActivityThread.java:4126)
03-19 14:15:02.170: E/AndroidRuntime(23242): at java.lang.reflect.Method.invokeNative(Native Method)
03-19 14:15:02.170: E/AndroidRuntime(23242): at java.lang.reflect.Method.invoke(Method.java:491)
03-19 14:15:02.170: E/AndroidRuntime(23242): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844)
03-19 14:15:02.170: E/AndroidRuntime(23242): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
03-19 14:15:02.170: E/AndroidRuntime(23242): at dalvik.system.NativeStart.main(Native Method)
Je Devrais mettre à jour ma qeustion avec mon code, si elle est ici.
public class AllResultsActivity extends TBActivity{
public String identifier,
feedIdentifier,
apiKey,
tagID,
titleName;
private ProcesReuest procesReuest;
public ArrayList<Integer> tempIDHolder = new ArrayList<Integer>();
public ArrayList<AllResultsItem> mAllResultsItem;
public AllResultsAdapter mAllResultsAdapter;
public ListView mListView;
private Context mContext;
private ViewFlipper mViewFlipper;
private TextView mTitleText;
private int itemsForLoad = 50;
private boolean firstRun = true;
private ProgressBar mLoadItemsIndicator;
private int visibleThreshold = 5;
private int mPage = 1;
private int previousTotal = 0;
private boolean loading = true;
private SharedPreferences mSettings;
private Editor mEdit;
private View footerView;
private int itemHolder;
@Override
public void onBackPressed() {
super.onBackPressed();
procesReuest.cancel(true);
AllResultsActivity.this.finish();
}
@Override
public void onCreate(Bundle savedInstanceState) {
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
this.setContentView(R.layout.all_results_view);
super.onCreate(savedInstanceState);
getExtras();
mContext = this;
itemsForLoad = 50;
loadItems(apiKey);
initListview();
}
private void initListview() {
mAllResultsItem = new ArrayList<AllResultsItem>();
mAllResultsAdapter = new AllResultsAdapter(this, mAllResultsItem);
mListView.setAdapter(mAllResultsAdapter);
mAllResultsAdapter.notifyDataSetChanged();
}
@Override
public void bindResources() {
mLoadItemsIndicator = (ProgressBar)findViewById(R.id.all_results_view_more_items_indicator);
mListView = (ListView)findViewById(R.id.all_results_listview);
mViewFlipper = (ViewFlipper)findViewById(R.id.all_results_view_viewflipper);
mTitleText = (TextView) findViewById(R.id.all_results_view_title_text);
mSettings = getSharedPreferences(WBAConstants.TRACEBUZZ, MODE_PRIVATE);
mEdit = mSettings.edit();
}
@Override
public void bindListeners() {
mListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View view, int id, long arg3) {
String url = (String) view.getTag(R.string.item_url);
Intent intnt = new Intent(AllResultsActivity.this, WebviewWithControllsActivity.class);
if(url.contains("twitter")) {
int UQID = (Integer)view.getTag(R.id.twitter_result_identifier);
String table = (String)view.getTag(R.string.twitter_table);
intnt.putExtra("UQID", UQID);
intnt.putExtra("apiKey", apiKey);
intnt.putExtra("table", table);
}
View bar = (View)findViewById(R.id.all_results_title_bar);
int barHeight = bar.getHeight();
intnt.putExtra("barHeight", barHeight);
intnt.putExtra("URL", url);
AllResultsActivity.this.startActivity(intnt);
}
});
mListView.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
Log.d("","totalItemCount = " + totalItemCount);
if (loading) {
if (totalItemCount > previousTotal) {
loading = false;
previousTotal = totalItemCount;
itemHolder = previousTotal;
}
}
if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) {
mLoadItemsIndicator.setVisibility(View.VISIBLE);
mListView.invalidate();
mPage++;
loadItems(apiKey);
loading = true;
} else {
}
}
});
}
private void loadItems(String passedApiKey) {
procesReuest = new ProcesReuest();
procesReuest.execute(identifier, feedIdentifier, passedApiKey);
}
public void getExtras() {
Bundle extras = getIntent().getExtras();
feedIdentifier = null;
tagID = null;
apiKey = null;
if(extras != null) {
identifier = extras.getString("identifier");
feedIdentifier = extras.getString("feedidentifier");
apiKey = extras.getString("apiKey");
titleName = extras.getString("tag_name");
tagID = extras.getString("tag_id");
if((titleName != null) && (!titleName.equals("null"))) {
mTitleText.setText(titleName);
}
}
}
public void displayDialog() {
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
dialog.setTitle("Error");
dialog.setMessage("Failed to contact server, check your Internet connection or try again later");
dialog.setNegativeButton("back", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
AllResultsActivity.this.finish();
}
});
dialog.show();
}
private synchronized void addSyncedItems() throws InterruptedException {
if(firstRun){
mAllResultsAdapter.setItems(mAllResultsItem);
firstRun = false;
}
mAllResultsAdapter.notifyDataSetChanged();
mListView.invalidate();
mLoadItemsIndicator.setVisibility(View.GONE);
}
/** Subclass for processing the ResultReqesut for the specified type **/
private class ProcesReuest extends AsyncTask<String, Void, Exception>{
Downloader downloader = new Downloader();
JSONObject result = null;
List<NameValuePair> postParams;
boolean timeOut;
@Override
protected Exception doInBackground(String... params) {
Log.d("","doInBackground " + apiKey);
try {
postParams = new ArrayList<NameValuePair>(2);
postParams.add(new BasicNameValuePair("api_key",apiKey));
postParams.add(new BasicNameValuePair("num","100"));
postParams.add(new BasicNameValuePair("feed_id", feedIdentifier));
postParams.add(new BasicNameValuePair("page", Integer.toString(mPage)));
postParams.add(new BasicNameValuePair("order", "time DESC"));
postParams.add(new BasicNameValuePair("tag_id", tagID));
postParams.add(new BasicNameValuePair("format", "json"));
Log.d("","postParams = " + postParams);
downloadJSON(postParams);
proccesJSON();
} catch (JSONException e) {
//TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Exception exception) {
Log.d("","onPostExecute");
try {
addSyncedItems();
} catch (InterruptedException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
try {
if(!result.getJSONObject("results").getString("result_count").equals("0")){
mViewFlipper.setDisplayedChild(2);
} else {
Log.d("","View 3");
mViewFlipper.setDisplayedChild(2);
}
} catch (Exception e) {
//TODO: handle exception
}
}
private void proccesJSON() throws JSONException, IOException {
String UIDHolderString = mSettings.getString(WBAConstants.UIDHOLDER, "empty");
JSONArray arrayHolder = null;
if(UIDHolderString.equals("empty")){
arrayHolder = new JSONArray();
} else {
arrayHolder = new JSONArray(UIDHolderString);
}
if(result != null){
JSONObject feedResults = result.getJSONObject("results").getJSONObject("result");
Log.d("","" + feedResults);
String uniqueItemID = null;
Iterator<String> feedResultIter = feedResults.keys();
while (feedResultIter.hasNext()) {
uniqueItemID = (String) feedResultIter.next();
Log.d("","" + uniqueItemID);
if(!uniqueItemID.equals("metaresult")) {
AllResultsItem item = new AllResultsItem();
if(UIDHolderString.contains(uniqueItemID)) {
item.setNewFeed(0);
} else {
item.setNewFeed(1);
arrayHolder.put(uniqueItemID);
}
JSONObject resultItem = feedResults.getJSONObject(uniqueItemID);
String typeFeed = resultItem.getString("type");
if(!typeFeed.contains("twitter") && typeFeed != null){
if(resultItem.has("tags") && resultItem.getString("tags")!= null) {
JSONObject tags = resultItem.getJSONObject("tags");
Iterator<String> tagIter = tags.keys();
ArrayList<String> tagHolder = new ArrayList<String>();
while (tagIter.hasNext()) {
String tagID = (String) tagIter.next();
String tagName = tags.getString(tagID);
tagHolder.add(tagName);
}
item.setTagNames(tagHolder.toString());
}
item.setType(typeFeed);
if((resultItem.has("title")) && (!resultItem.isNull("title")) && (!resultItem.getString("title").equals("null") )) {
item.setResultTitle(resultItem.getString("title"));
}
if(resultItem.has("unique_id")) {
item.setResultIdentifier(Integer.parseInt(resultItem.getString("unique_id")));
}
if(resultItem.has("src_link") && (resultItem.getString("src_link") != null)) {
item.setMessageURL(resultItem.getString("src_link"));
}
if(resultItem.has("date_time")) {
item.setDate( resultItem.getString("date_time"));
}
if(resultItem.has("description")) {
item.setMessage(resultItem.getString("description"));
}
} else if(resultItem.getString("type").contains("twitter")){
Icon icon = new Icon();
if((resultItem.has("title")) && (!resultItem.isNull("title")) && (!resultItem.getString("title").equals("null"))) {
item.setUserTwitter(resultItem.getString("title"));
}
if(resultItem.has("unique_id")) {
item.setIdentifier(Integer.parseInt(resultItem.getString("unique_id")));
}
if(resultItem.has("src_link") && (resultItem.getString("src_link") != null)) {
item.setMessageURL(resultItem.getString("src_link"));
}
if(resultItem.has("date_time")) {
item.setDate(resultItem.getString("date_time"));
}
if(resultItem.has("description")) {
item.setMessageText(resultItem.getString("description"));
}
if(resultItem.has("image_link")) {
if(!resultItem.has("null")){
icon.setImageURL(resultItem.getString("image_link"));
}
}
if(resultItem.has("table")) {
item.setTable(resultItem.getString("table"));
}
item.setType(typeFeed);
item.addIconsObject(icon);
if(resultItem.has("tags") && resultItem.getString("tags")!= null) {
JSONObject tags = resultItem.getJSONObject("tags");
Iterator<String> tagIter = tags.keys();
ArrayList<String> tagHolder = new ArrayList<String>();
while (tagIter.hasNext()) {
String tagID = (String) tagIter.next();
String tagName = tags.getString(tagID);
tagHolder.add(tagName);
}
item.setTagNames(tagHolder.toString());
}
}
mAllResultsItem.add(item);
}
}
mEdit.putString(WBAConstants.UIDHOLDER, arrayHolder.toString());
mEdit.commit();
}
}
public boolean downloadJSON(List<NameValuePair>postParams) {
try {
result = downloader.getJSONFromURL("http://www.example.com/webservice/get_feed_results.php", true, postParams);
} catch (ClientProtocolException e) {
//TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
//TODO Auto-generated catch block
e.printStackTrace();
} catch (JSONException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}
}
}
La raison de la Synchronisées méthode était juste pour essayer d'obtenir la carte et de la liste de la mise à jour à la même heure.
où ce code a été écrit en arrière-plan() ou dans postExecution()?
invalidate(); et requestLayout(); sont redondantes si vous avez seulement besoin d'actualiser la liste.
Quelle est la raison derrière l'appel d'une méthode synchronisée de
J'ai mis à Jour ma Question, merci d'avance
Double Possible de Android, ListView IllegalStateException: "Le contenu de la carte a changé, mais ListView n'a pas reçu une notification"
invalidate(); et requestLayout(); sont redondantes si vous avez seulement besoin d'actualiser la liste.
Quelle est la raison derrière l'appel d'une méthode synchronisée de
onPostExecute
?J'ai mis à Jour ma Question, merci d'avance
Double Possible de Android, ListView IllegalStateException: "Le contenu de la carte a changé, mais ListView n'a pas reçu une notification"
OriginalL'auteur Maikel Bollemeijer | 2012-03-19
Vous devez vous connecter pour publier un commentaire.
Selon l'extrait de code, il existe quelques méthodes (bindResources() et bindListeners (), etc.) marqué comme @Override qui ne sont ni hérité de la officielle de l'API ni explicitement appelé à AllResultsActivity. Assumer ces sont correctement mis en œuvre et impliqués dans la super-classe ou ailleurs. Le problème que je vois dans votre code est:
Le problème, c'est quand AysncTask exécuté et onPostExecute() appelée (où mAllResultsAdapter.notifyDataSetChanged(); appelée), la Carte n'est pas lié à la liste encore. Simplement en appelant initListview(); avant loadItems(apiKey); devrait faire la java.lang.IllegalStateException: s'en va.
Mise à jour:
J'ai pris un regard profond dans votre code, le problème est la liste de tableaux qui se lie à la Carte est changé dans le thread d'arrière-plan:
Votre carte est effectivement modifiés à partir d'un thread d'arrière-plan, exactement comme l'exception suggéré. La solution est de le déplacer vers thread d'INTERFACE utilisateur ou tout simplement en l'enveloppant avec runOnUiThread():
Espère que cette aide.
Toujours pas de chance, Mais la chose étrange est. la plupart du temps ça fonctionne, tout simplement, mais rarement, il se bloque juste.
Qu'entendez-vous par rarement, il se bloque juste? même exception?
oui, la Plupart du temps, il fonctionne. et parfois il se bloque juste au hasard. Maby il a quelque chose de todo que je suis en train de tester sur les appareils Android 4.0, mais la plate-forme cible est 2.3.3 , je devrais courir quelques tests supplémentaires sur un 2.3.3 appareil
Il y a beaucoup de raisons possibles résultant de cette imprévisible exécution de comportement, il peut-être lfor exampe, la problématique de la ligne de code n'est pas exécuté dans l'état de la liste vide (c'est à dire rien à montrer). sans plus de détails,je ne peux pas dire la cause exacte.
OriginalL'auteur yorkw
Je sais que ce fil est de 3 ans. J'ai été demandé de fixer un Le contenu de la carte a changé, mais ListView n'a pas reçu une notification erreur dans le code existant. J'ai examiné les usages de
Timer
et ajouté un runOnUiThread(), mais le problème est toujours montré. Mais tout a été fait sur le thread de l'INTERFACE utilisateur!En fait, la
ListView
était affichant les données basées sur des fichiers système de répertoire -- équivalente à l'affichage de tous les fichiers dans un répertoire dans unListView
. Les fonctionsgetCount()
etgetView()
ont été la lecture de données à partir du répertoire, et quand Android pourrait détecter que le nombre de fichiers a changé, il a jeté une exception.La solution a été de mettre en cache la liste des répertoires et laisse le temps de rafraîchissement.
Oui, les modifications sur le disque pourrait ne pas être immédiatement reflété dans l'affichage plus... mais le mieux est l''ennemi du bien.
OriginalL'auteur 18446744073709551615