[問題] java.lang.IllegalStateException

看板AndroidDev作者 (joker)時間10年前 (2015/10/06 23:44), 編輯推噓1(1038)
留言39則, 4人參與, 最新討論串1/1
各位前輩大家好,小弟接觸android沒多久還是位新手, 目前在做作品時遇到了一個瓶頸,是在ListView.setAdapter() 短時間內大量重複更新時跳出以下錯誤: 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. Make sure your adapter calls notifyDataSetChanged() when its content changes. [in ListView(2131296313, class android.widget.ListView) with Adapter(class com.example.avalon.PlayerAdapter)] 以下是小弟寫的Adapter的程式碼: public class PlayerAdapter extends BaseAdapter { private LayoutInflater playersInflater; public List<Player> playerslist; public PlayerAdapter(Context context, List<Player> playerslist) { // TODO 自動產生的建構子 Stub if(playerslist!=null){ playersInflater=LayoutInflater.from(context); this.playerslist=playerslist; PlayerAdapter.this.notifyDataSetChanged(); } } @Override public int getCount() { // TODO 自動產生的方法 Stub return (playerslist==null)? 0 : playerslist.size(); } @Oerride public Object getItem(int position) { // TODO 自動產生的方法 Stub return playerslist.get(position); } @Override public long getItemId(int position) { // TODO 自動產生的方法 Stub return playerslist.indexOf(getItem(position)); } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO 自動產生的方法 Stub if(playerslist.size()!=0){ try{ convertView=playersInflater.inflate (R.layout.players_list_item, null); ImageView iv_Players_Status=(ImageView) convertView.findViewById(R.id.IV_Players_Status); TextView tv_Players_Order=(TextView) convertView.findViewById(R.id.TV_Players_Order); TextView tv_Players_Anonymous=(TextView) convertView.findViewById(R.id.TV_Players_Anonymous); iv_Players_Status.setImageResource (playerslist.get(position).getStatus()); tv_Players_Order.setText(String.valueOf (playerslist.get(position).getOrder()).toString()); tv_Players_Anonymous.setText (playerslist.get(position).getAnonymity()); }catch(Exception e){ e.printStackTrace(); Log.e("text","PlayerAdapter="+e.toString()); } return convertView; }else{ convertView=playersInflater.inflate(R.layout.null_layout, null); return convertView; } } } 這幾天爬文有看到getCount()內寫成 return (playerslist==null)? 0 : playerslist.size(); 還有在更新資料時呼叫notifyDataSetChanged()通知系統更新Adapter 可是在大量更新時app還是會崩潰跳出此錯誤 有聽人說可以在更新時隱藏按鈕,到更新完後在顯示按鈕 但是小弟是寫socket連伺服器,所以可以多人更新所以以上方法可能無法解決 還希望各位可以協助解決,謝謝~ -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 1.175.134.228 ※ 文章網址: https://www.ptt.cc/bbs/AndroidDev/M.1444146266.A.E50.html

10/07 01:20, , 1F
Socket有沒有開另外一個Thread,有的話Socket跟UI資訊
10/07 01:20, 1F

10/07 01:20, , 2F
更新也很容易造成兩個Thread在協同資料上有困難,不
10/07 01:20, 2F

10/07 01:20, , 3F
知道是不是這個問題
10/07 01:20, 3F

10/07 01:28, , 4F
只要有thread影響到Ui執行緒就會跳出錯誤,handler在
10/07 01:28, 4F

10/07 01:28, , 5F
大量資訊處理也會因為資料順序更新問題使得ui執行緒
10/07 01:28, 5F

10/07 01:28, , 6F
收到指令時出問題
10/07 01:28, 6F

10/07 12:37, , 7F
我有用一個Thread在背景做接收
10/07 12:37, 7F

10/07 12:38, , 8F
接收完後再用runOnUiThread()做ListView.setAdapter()
10/07 12:38, 8F

10/07 12:41, , 9F
之前有過出現null值的錯誤,所以我在接收時有用ArrayList<>
10/07 12:41, 9F

10/07 12:43, , 10F
儲存背景接收到的資料再作setAdapter()才不被下一個接收覆蓋
10/07 12:43, 10F

10/07 12:47, , 11F
之前因為這個問題在爬文時有看人說過
10/07 12:47, 11F

10/07 12:48, , 12F
可能是在大量處理時adapter會改由Thread執行,而非UI
10/07 12:48, 12F

10/07 12:48, , 13F
在呼叫notifyDataSetChanged()時才會產生該錯誤
10/07 12:48, 13F

10/07 13:03, , 14F
只是不知道該如何解決
10/07 13:03, 14F

10/07 18:36, , 15F
你背景thread和UI thread在動同一個adapter instance?
10/07 18:36, 15F

10/07 18:37, , 16F
應該背景接到list後,UI thread把那個list內容copy到
10/07 18:37, 16F

10/07 18:37, , 17F
adapter裡的list,再notifyDataSetChanged就好吧
10/07 18:37, 17F

10/07 22:04, , 18F
我背景只有做接收到ArrayList<>
10/07 22:04, 18F

10/07 22:05, , 19F
而後來的存取ArrayList<>與adapter裡的list,再到
10/07 22:05, 19F

10/07 22:06, , 20F
都是使用runOnUiThread()完成,而notifyDataSetChanged是放在
10/07 22:06, 20F

10/07 22:06, , 21F
adapter內,如文中程式這樣,我不確定是不是有用錯
10/07 22:06, 21F

10/07 22:10, , 22F
目前只有在大量處理時會跳錯誤,我想說最多10個人同時點擊
10/07 22:10, 22F

10/07 22:11, , 23F
所以為了測試,在伺服器寫了點擊一次送10次更改
10/07 22:11, 23F

10/07 22:11, , 24F
在瘋狂點擊幾秒後才會出現這個錯誤
10/07 22:11, 24F

10/07 23:01, , 25F
getItemId() 可直接回傳position
10/07 23:01, 25F

10/07 23:02, , 26F
你怎麼把更新過的資料copy到adapter的?
10/07 23:02, 26F

10/07 23:04, , 27F
要記得arraylist裡的東西都是物件,直接用 = 是指到同
10/07 23:04, 27F

10/07 23:04, , 28F
一個reference
10/07 23:04, 28F

10/07 23:06, , 29F
this.playerslist=playerslist; 你建構子中的這行就
10/07 23:06, 29F

10/07 23:06, , 30F
很可能出問題
10/07 23:06, 30F

10/07 23:16, , 31F
你也可以改用或參考ArrayAdapter的程式碼,它是 threa
10/07 23:16, 31F

10/07 23:16, , 32F
d-safe
10/07 23:16, 32F

10/07 23:49, , 33F
感謝大大,改成new一個List<Player>再用addAll()複製過去
10/07 23:49, 33F

10/07 23:51, , 34F
解決這個錯誤了,只是我在remove時貌似出現新的錯誤
10/07 23:51, 34F

10/07 23:51, , 35F
java.util.ConcurrentModificationException
10/07 23:51, 35F

10/07 23:54, , 36F
有用Iterator嗎?這個錯誤google一下有不少人討論
10/07 23:54, 36F

10/07 23:57, , 37F
抱歉剛剛以解決,原來是我用Log勘查ArrayList<>
10/07 23:57, 37F

10/07 23:58, , 38F
每次存取都查看ArrayList<>累積多少,可能是有些被Thread刪除
10/07 23:58, 38F

10/07 23:58, , 39F
才會跳出這個錯誤
10/07 23:58, 39F
文章代碼(AID): #1M4-nQvG (AndroidDev)