2016-04-04 26 views
1

這是我在Stack Overflow中的第一個問題,我一直在Android上構建一個簡單的聊天應用程序,它從在線數據庫加載聊天記錄,它將會使用自定義消息適配器以列表視圖顯示。Android聊天應用程序:消息適配器不正確更新列表視圖中的項目

這裏是程序的當前狀態:

Demo

然而,列表項的佈局不下來數組列表中的第六聊天消息後正確的,下面所有的聊天消息重複前6條消息的佈局。

這裏是我的適配器代碼:

public class messageAdapter extends ArrayAdapter<chatMessage> { 

private Activity activity; 
private List<chatMessage> messages; 

public messageAdapter(Activity context, int resource, List<chatMessage> objects) { 
    super(context, resource, objects); 
    this.activity = context; 
    this.messages = objects; 
} 

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    ViewHolder holder; 
    LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE); 

    int layoutResource = 0; // determined by view type 
    chatMessage chatMessage = getItem(position); 
    int viewType = getItemViewType(position); 

    if (chatMessage.isMine()) { 
     layoutResource = R.layout.chat_bubble_right; 
    } else { 
     layoutResource = R.layout.chat_bubble_left; 
    } 

    if (convertView != null) { 
     holder = (ViewHolder) convertView.getTag(); 
    } else { 
     convertView = inflater.inflate(layoutResource, parent, false); 
     holder = new ViewHolder(convertView); 
     convertView.setTag(holder); 
     Log.d("ViewID", "generated"); 
    } 

    //set message content 
    holder.message.setText(chatMessage.getContent()); 

    return convertView; 
} 

@Override 
public int getViewTypeCount() { 
    // return the total number of view types. this value should never change 
    // at runtime 
    return 2; 
} 

@Override 
public int getItemViewType(int position) { 
    // return a value between 0 and (getViewTypeCount - 1) 
    return position % 2; 
} 

private class ViewHolder { 
    private TextView message; 

    public ViewHolder(View v) { 
     message = (TextView) v.findViewById(R.id.txt_msg); 
    } 
} 

這是我的聊天消息加載到數組列表的方法:

private class getChatHistory extends AsyncTask<DBConnection,Long,JSONArray> { 
    @Override 
    protected JSONArray doInBackground(DBConnection... params) { 
     return params[0].getChatHistory(userID); 
    } 

    @Override 
    protected void onPostExecute(JSONArray jsonArray) { 

     chatData = jsonArray; 

     if (chatData != null) 
     { 
      for (int i = 0; i < chatData.length(); i++) 
      { 
       JSONObject currentItem = null; 

       try 
       { 
        currentItem = chatData.getJSONObject(i); 
        int msgID = currentItem.getInt("MessageID"); 
        String currentText = currentItem.getString("MessageContent"); 
        int senderID = currentItem.getInt("SenderID"); 
        int receiverID = currentItem.getInt("ReceiverID"); 
        chatMessage currentMessage = new chatMessage(currentText, senderID, userID); 
        Log.d("Is Mine", Boolean.toString(currentMessage.isMine())); 
        messageHistory.add(currentMessage); 
        DBAdapter.notifyDataSetChanged(); 

       } catch (JSONException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 
} 

這裏是我從所獲得的JSONArray我跑的PHP文件:

[{"MessageID":"1","SenderID":"1","ReceiverID":"8","Duration":"2.4","MessageContent":"agnblean liajiaj vliwv fla","MessageLength":"26","Status":"received","Date":"2016-04-04 14:00:00"}, 
{"MessageID":"2","SenderID":"8","ReceiverID":"1","Duration":"3.1","MessageContent":"akwuehrgeubwfcofawve","MessageLength":"20","Status":"received","Date":"2016-04-04 17:00:00"}, 
{"MessageID":"3","SenderID":"8","ReceiverID":"1","Duration":"3.1","MessageContent":"akwuehrgeubwfjurawve","MessageLength":"20","Status":"received","Date":"2016-04-04 17:00:05"}, 
{"MessageID":"4","SenderID":"8","ReceiverID":"1","Duration":"3.1","MessageContent":"akwuehrgeubwalwrawve","MessageLength":"20","Status":"received","Date":"2016-04-04 17:00:10"}, 
{"MessageID":"5","SenderID":"1","ReceiverID":"8","Duration":"3.1","MessageContent":"akwuehrgeubwalwrawve","MessageLength":"20","Status":"received","Date":"2016-04-04 17:01:10"}, 
{"MessageID":"8","SenderID":"1","ReceiverID":"8","Duration":"4.6","MessageContent":"vsjkgkgredjegwhkaga","MessageLength":"23","Status":"received","Date":"2016-04-05 05:00:00"}, 
{"MessageID":"9","SenderID":"8","ReceiverID":"1","Duration":"5.2","MessageContent":"agrlanwligna","MessageLength":"21","Status":"received","Date":"2016-04-06 00:00:00"}, 
{"MessageID":"10","SenderID":"8","ReceiverID":"1","Duration":"7.2","MessageContent":"akewgaughurawaarg","MessageLength":"12","Status":"received","Date":"2016-04-12 00:00:00"}, 
{"MessageID":"11","SenderID":"1","ReceiverID":"8","Duration":"7.2","MessageContent":"wgkakjrgnjange","MessageLength":"41","Status":"received","Date":"2016-04-15 00:00:00"}, 
{"MessageID":"12","SenderID":"1","ReceiverID":"8","Duration":"4.67","MessageContent":"yikes","MessageLength":"5","Status":"received","Date":"2016-04-21 00:00:00"}, 
{"MessageID":"13","SenderID":"8","ReceiverID":"1","Duration":"8.2","MessageContent":"iobanoine","MessageLength":"4","Status":"received","Date":"2016-04-30 00:00:00"}] 

所以我認爲這會產生正確的佈局聊天曆史,其中活性用戶是用戶ID = 1,並且所有與發送者ID的消息= 1應在列表視圖的右手側,而是我得到這個:

screenshot

這是列表視圖中第5-8個元素的截圖,但第7個元素位於右側而不是左側,後面的元素繼續重複之前的6元素的模式。我檢查了轉換視圖的日誌,它只顯示了6次,是否與這個錯誤有關呢?我該如何解決適配器沒有正確定位列表項資源的問題?

EDIT:我已經改變了getItemViewType()的覆蓋到這個

@Override 
public int getItemViewType(int position) { 
    chatMessage chatMessage = getItem(position); 
    if (chatMessage.isMine()) { 
     return 0; 
    } else { 
     return 1; 
    } 
} 

我也已刪除了重寫方法爲getViewTypeCount,並在getView改變條件的位()方法:

int viewType = getItemViewType(position); 

    if (viewType==0) { 
     layoutResource = R.layout.chat_bubble_right; 
    } else { 
     layoutResource = R.layout.chat_bubble_left; 
    } 

現在聊天消息列表按正常順序排列到第8個元素,然後順序再次變得不正確。

EDIT 2

我有跟蹤日誌列表項的產生(即新項目)的數量,這是結果向下滾動到列表視圖底部後,我得到:

04-06 19:23:54.894 11202-11202/com.example.user.normalinterface D/ViewID: generated 
04-06 19:23:54.907 11202-11202/com.example.user.normalinterface D/ViewID: generated 
04-06 19:23:54.912 11202-11202/com.example.user.normalinterface D/ViewID: generated 
04-06 19:23:54.914 11202-11202/com.example.user.normalinterface D/ViewID: generated 
04-06 19:23:56.850 11202-11202/com.example.user.normalinterface D/ViewID: generated 

這是在反正與我的問題?它看到列表視圖中的所有後續記錄都從列表中的前5個項目重複該模式。

+0

我遇到了一個非常類似的問題,當我找到一個問題時,我會發布我的解決方案。 – kiwicomb123

回答

0

我認爲它來自於getViewTypeCount()方法。在這裏你說你有兩種不同的佈局。用方法getItemViewType()你說,不同的類型是2條消息中的一條。但是你不要使用getView方法中的類型。

顯然,你不需要這些2種類型,所以我建議你只是刪除了2種方法: getViewTypeCount()getItemViewType()

我不認爲你需要他們在你的情況。

編輯: 你實際上需要這些方法,但你嚴重凌駕getItemViewType

@Override 
public int getItemViewType(int position) { 
    chatMessage chatMessage = getItem(position); 
    if (chatMessage.isMine()) { 
     return 0; 
    } else { 
     return 1; 
    } 
} 
+0

之後,我刪除了上面的兩個方法記錄正確的第8個元素,然後佈局變得不正確了... –

+0

我的不好,請參閱編輯解決方案 – Andros

+0

我已經改變了getItemViewType()方法,並且也稍微改變了佈局資源的條件,但這很奇怪,因爲在調試模式下,我已經記錄下來,看看這個條件是否會給我正確的資源,它工作得很好。不知何故,第8個元素後資源沒有正確加載。 –

0

以我的經驗,但未必是有關這一點,你需要調用notifyDataSetChanged()的適配器,所以成立了一個名爲refreshData方法的適配器是這樣的:

public void refreshData(ArrayList<yourList> data) { 
    mValues.clear(); 
    mValues.addAll(data); 
    notifyDataSetChanged(); 
} 

並致電您的活動:

mAdapter.refreshData(newData) 

以新數據爲參數。

此外,請確保您引用適配器類正確,所以嘗試添加到您的類的開頭:

private final DBAdapter mAdapter; 

然後在getChaHistory補充:

mAdapter = DBAdapter 

的想法是,你有正確引用的適配器的句柄。請注意,您現在調用mAdapter.refreshData(newData)而不是DBAdapter.refreshData(newdata)的前一個答案的更改。真的,我認爲你應該把適配器傳給班上,這正是我所做的,但你可以試試這種方式,看看你怎麼樣?

+0

我將該方法添加到我的適配器中,但由於某種原因,我無法從我的聊天頁面類中調用它... –

+0

沒關係......我通過將適配器初始化爲陣列適配器而不是實際的適配器我創建的類,多麼愚蠢的錯誤,但感謝您的幫助! –

+0

不錯的一個,至少你到過那裏的朋友!我確實想知道消息適配器...... :) – partynose

0

這會正常工作,但不會一樣快。如果「isMine()」爲true,那麼它決定實例化哪個佈局取決於值。如果「isMine()」爲true,那麼包含右對齊的TextView的佈局被實例化,否則其他佈局被實例化(TextView左對齊)

@Override 
public View getView(int position, View convertView, ViewGroup parent){ 

    if(messages.get(position).isMine()){ 
     item = ((Activity)context).getLayoutInflater().inflate(R.layout.chat_bubble_right,null); 
    } 
    else{ 
     item = ((Activity)context).getLayoutInflater().inflate(R.layout.chat_bubble_left,null); 
    } 
    // set the text in the view. 
    ((TextView) item.findViewById(R.id.chat_text)).setText(data.get(position).getMessage()); 
    return item; 
} 

的chat_text id表示TextView的實例化佈局內(兩個佈局包含具有ID chat_text一個TextView)
我用這個谷歌IO事件作爲一種資源:。
https://www.youtube.com/watch?v=wDBM6wVEO70

相關問題