2016-03-04 193 views
0

我有一個自定義的ArrayAdapter PlayerAdapter指的是玩家的ArrayList。我正在嘗試將新玩家添加到ArrayList,然後通過notifyDataSetChanged更新ListView,但它導致了崩潰。我想我需要提供一些額外的覆蓋到我的自定義PlayerAdapter,但我不知道需要修復什麼。我搜索了其他主題here,但一切都略有不同。我敢肯定,我失去了一些東西明顯...自定義arrayadapter notifyDataSetChanged導致崩潰

崩潰日誌

03-04 09:43:50.836 3016-3016/? E/AndroidRuntime: FATAL EXCEPTION: main 
              Process: com.laudev.android.crossoff, PID: 3016 
              java.lang.IndexOutOfBoundsException: Invalid index 4, size is 4 
               at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255) 
               at java.util.ArrayList.get(ArrayList.java:308) 
               at com.laudev.android.crossoff.PlayerAdapter.getView(PlayerAdapter.java:53) 
               at android.widget.AbsListView.obtainView(AbsListView.java:2347) 
               at android.widget.ListView.makeAndAddView(ListView.java:1864) 
               at android.widget.ListView.fillDown(ListView.java:698) 
               at android.widget.ListView.fillSpecific(ListView.java:1356) 
               at android.widget.ListView.layoutChildren(ListView.java:1651) 
               at android.widget.AbsListView.onLayout(AbsListView.java:2151) 
               at android.view.View.layout(View.java:15671) 
               at android.view.ViewGroup.layout(ViewGroup.java:5038) 
               at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703) 
               at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557) 
               at android.widget.LinearLayout.onLayout(LinearLayout.java:1466) 
               at android.view.View.layout(View.java:15671) 
               at android.view.ViewGroup.layout(ViewGroup.java:5038) 
               at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579) 
               at android.widget.FrameLayout.onLayout(FrameLayout.java:514) 
               at android.view.View.layout(View.java:15671) 
               at android.view.ViewGroup.layout(ViewGroup.java:5038) 
               at android.support.v7.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:435) 
               at android.view.View.layout(View.java:15671) 
               at android.view.ViewGroup.layout(ViewGroup.java:5038) 
               at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579) 
               at android.widget.FrameLayout.onLayout(FrameLayout.java:514) 
               at android.view.View.layout(View.java:15671) 
               at android.view.ViewGroup.layout(ViewGroup.java:5038) 
               at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703) 
               at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557) 
               at android.widget.LinearLayout.onLayout(LinearLayout.java:1466) 
               at android.view.View.layout(View.java:15671) 
               at android.view.ViewGroup.layout(ViewGroup.java:5038) 
               at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579) 
               at android.widget.FrameLayout.onLayout(FrameLayout.java:514) 
               at android.view.View.layout(View.java:15671) 
               at android.view.ViewGroup.layout(ViewGroup.java:5038) 
               at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2086) 
               at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1843) 
               at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1061) 
               at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5885) 
               at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767) 
               at android.view.Choreographer.doCallbacks(Choreographer.java:580) 
               at android.view.Choreographer.doFrame(Choreographer.java:550) 
               at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753) 
               at android.os.Handler.handleCallback(Handler.java:739) 
               at android.os.Handler.dispatchMessage(Handler.java:95) 
               at android.os.Looper.loop(Looper.java:135) 
               at android.app.ActivityThread.main(ActivityThread.java:5254) 
               at java.lang.reflect.Method.invoke(Native Method) 
               at java.lang.reflect.Method.invoke(Method.java:372) 
               at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) 
               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698) 

PlayerAdapter.java

public class PlayerAdapter extends ArrayAdapter<Player> { 

Context context; 
int layoutResourceId; 
ArrayList<Player> data; 

public PlayerAdapter(Context context, int layoutResourceId, ArrayList<Player> data) { 
    super(context, layoutResourceId, data); 
    this.layoutResourceId = layoutResourceId; 
    this.context = context; 
    this.data = new ArrayList<Player>(data); 
} 

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    View row = convertView; 
    PlayerHolder holder = null; 

    if(row == null) 
    { 
     LayoutInflater inflater = ((Activity)context).getLayoutInflater(); 
     row = inflater.inflate(layoutResourceId, parent, false); 

     holder = new PlayerHolder(); 
     holder.imgIcon = (ImageView)row.findViewById(R.id.imgIcon); 
     holder.txtName = (TextView)row.findViewById(R.id.txtName); 
     holder.txtScore = (TextView)row.findViewById(R.id.txtScore); 

     row.setTag(holder); 
    } 
    else 
    { 
     holder = (PlayerHolder)row.getTag(); 
    } 

    Player player = data.get(position); 
    holder.txtName.setText(player.name); 
    holder.imgIcon.setImageResource(player.icon); 
    holder.txtScore.setText("" + player.score); 

    return row; 
    } 

static class PlayerHolder 
    { 
    ImageView imgIcon; 
    TextView txtName; 
    TextView txtScore; 
    } 
} 

Player.java

public class Player { 
public int icon; 
public String name; 
public int score; 
public Player(){ 
    super(); 
    } 

public Player(int icon, String name, int score) { 
    super(); 
    this.icon = icon; 
    this.name = name; 
    this.score = score; 
    } 
} 

並且最後在MainActivity .java

public class MainActivity extends AppCompatActivity { 

private PlayerAdapter adapter; 
private ListView listViewPlayers; 
private List<Player> player_data; 

// Called when activity is first created 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    // Initialize view with 4 players 
    player_data = new ArrayList<Player>(); 
    for (int i = 1; i < 5; i++) { 
     player_data.add(new Player(R.drawable.red, "Player " + i, 0)); 
    } 

    // Set adapter with the four players above 
    adapter = new PlayerAdapter(this, 
      R.layout.simplerow, (ArrayList<Player>) player_data); 

    // Hook up ListView with adapter 
    listViewPlayers = (ListView)findViewById(R.id.playerList); 
    listViewPlayers.setAdapter(adapter); 
} 

// press button to add a new player to ListView 
public void addPlayer (View v) { 
    int nextPlayerNum = player_data.size() + 1; 
    player_data.add(new Player(R.drawable.blue, "Player " + nextPlayerNum, 0)); 
    // EDIT: commenting out this line since not necessary. Still seeing crash. 
    // adapter.add(new Player(R.drawable.blue, "Player " + nextPlayerNum, 0)); 
    adapter.notifyDataSetChanged(); 
} 

} 
+0

你可以發佈崩潰日誌嗎? – Francesc

回答

0

這似乎回答你自己的問題在這裏皺起了眉頭......但我會做它無論如何。問題出在PlayerAdapter.java的構造函數中。該生產線

this.data = new ArrayList<Player>(data); 

this.data = data; 

,使新ArrayAdapter和MainActivity.java全局列表指的是同一個對象來代替。感謝大家幫助我到達這裏......我使用調試器,發現有一個出界異常,然後發現有兩個不同的ArrayList在發揮作用。

0
player_data.add(new Player(R.drawable.blue, "Player " + nextPlayerNum, 0)); 
adapter.add(new Player(R.drawable.blue, "Player " + nextPlayerNum, 0)); 
adapter.notifyDataSetChanged(); 

這是什麼意思?

你不應該添加這樣的項目。

相反,你可以這樣做,

申報和全球初始化數組列表。

ArrayList<Player> list = new ArrayList<>(); 

然後每次你應該在數組列表中添加數據然後調用。下面一行

list.add(PLAYER OBJECT); 
adapter.notifyDataSetChanged() 
0

評論,並嘗試一次

adapter.add(new Player(R.drawable.blue, "Player " + nextPlayerNum, 0)); 

不要求你已經在列表中添加數據。

+0

我繼續並將adapter.add註釋掉了,但我仍然看到崩潰。我在調用'player_data.add(new Player(R.drawable.blue,「Player」+ nextPlayerNum,0));'後驗證'player_data'和'adapter'的長度都是5,'但是一旦我調用'adapter .notifyDataSetChanged()'它崩潰 –