2016-02-16 59 views
0

我正在使用自定義ArrayAdapter的Android應用程序的消息傳遞屏幕上工作,以便將成員之間發送的消息佈局爲聊天泡泡。數據在onCreate()期間被下載,JSON被解析並加載到適配器中,一次一個消息,在onPostExecute()中。日誌證實了這一部分。自定義ArrayAdapter只顯示1個JSON項目

適配器被加載到位於EditText字段上方的ListView和新消息的Send按鈕中。下面是片段java,其中包括修改後的ArrayAdapter類以及用於UI和消息行佈局的兩個XML文件。

package com.davepeyton.android.seekbromance; 

import android.annotation.TargetApi; 
import android.os.AsyncTask; 
import android.os.Build; 
import android.os.Bundle; 
import android.support.v4.app.FragmentManager; 
import android.support.v4.app.Fragment; 
import android.text.Editable; 
import android.text.TextWatcher; 
import android.util.Log; 
import android.view.Gravity; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.Button; 
import android.widget.LinearLayout; 
import android.widget.TextView; 
import android.widget.EditText; 
import android.widget.ArrayAdapter; 
import android.widget.ListView; 

import org.apache.http.NameValuePair; 
import org.apache.http.message.BasicNameValuePair; 
import org.json.JSONArray; 
import org.json.JSONException; 
import org.json.JSONObject; 

import java.text.SimpleDateFormat; 
import java.util.Date; 
import java.util.ArrayList; 
import java.util.List; 

/* 
* This fragment displays a simple list view using a custom array adapter, with a TextEdit 
* field for sending new messages. 
* 
* The layout 'dresses up' the messages (of class BroChatMsg) to look like chat balloons. 
*/ 

public class BrofileBroChatFragment extends Fragment { 

    public static final String EXTRA_BROFILE_ID = "com.davepeyton.android.seekbromance.brofile_id"; 
    // no need to fetch the whole brofile here - it doesn't get displayed or altered 
    // private static final String url_fetch_brofile = "http://www.seekbromance.com/android_connx/fetch_brofile.php"; 
    private static final String url_fetch_messages = "http://www.seekbromance.com/android_connx/fetch_messages.php"; 

    private int mCurrUserMemberId; // the member ID for the logged-in user 
    // private String brofile_id; // parameter for fetch_brofile.php 

    private int mConnectFailed = 0; // for HTTP exceptions and the like 

    int brofileId; 

    // parameters for fetch_message.php 
    private String sender_id = "19"; 
    private String receiver_id = "2905"; 
    private int sid; 
    private int rid; 

    // JSON parser class 
    JSONParser jsonParser = new JSONParser(); 

    // JSON node names to be used in this fragment 
    private static final String TAG_SUCCESS = "success"; 
    private static final String TAG_MESSAGES = "messages"; 
    private static final String TAG_SID = "sid"; 
    private static final String TAG_RID = "rid"; 
    private static final String TAG_BODY = "body"; 
    private static final String TAG_TIMESTAMP = "timestamp"; 

    private static BroChatMsg sBroChatMsg; 
    private ArrayList<BroChatMsg> mRetrievedMessages; // originally took the message data, now used only to initialize the adapter. 
    private MessageAdapter mAdapter; 

    private String mQuickString = ""; 

    private EditText mNewMsgField; 
    private Button mSendMessageBtn; 
    private ListView mLv; 

    private String newMessageBody = ""; 


    public static BrofileBroChatFragment newInstance(int brofileId) { 
     Bundle args = new Bundle(); 
     args.putInt(EXTRA_BROFILE_ID, brofileId); 

     BrofileBroChatFragment fragment = new BrofileBroChatFragment(); 
     fragment.setArguments(args); 
     return fragment; 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setRetainInstance(true); 

     //Will probably need these later to get back to calling intent 
     // get the ID of the Brofile to display from the calling intent 
     brofileId = getArguments().getInt(EXTRA_BROFILE_ID); 
     mCurrUserMemberId = 19; // quick set for testing 


     //mCurrUserBrofileId = 25; // this is a "full" dummy profile in the SB database; used for testing*/ 

     sBroChatMsg = new BroChatMsg(); 
     mRetrievedMessages = new ArrayList<BroChatMsg>(); 
     mAdapter = new MessageAdapter(mRetrievedMessages); 

     //sid 19 and rid 2905 are for testing 
     sid = 19; 
     rid = 2905; 
     sender_id = String.valueOf(sid); 
     receiver_id = String.valueOf(rid); 

     String logMsg = "Requesting sid = " + sender_id + " receiver_id = " + receiver_id; 
     Log.d("Actions OnCreate", logMsg); 

     new FetchMessages().execute(); 
    } 

    class FetchMessages extends AsyncTask<String, Void, JSONObject> { 

     @Override 
     protected JSONObject doInBackground(String... strings) { 
      JSONObject json = null; 

      // Set up parameters for the PHP 
      List<NameValuePair> parameters = new ArrayList<NameValuePair>(); 
      parameters.add(new BasicNameValuePair("id1", sender_id)); 
      parameters.add(new BasicNameValuePair("id2", receiver_id)); 

      // Make the HTTP request 
      json = jsonParser.makeHttpRequest(url_fetch_messages, "GET", parameters); 

      // Log the JSON response 
      Log.d("Single Message Details", json.toString()); 

      return json; 
     } 

     @Override 
     protected void onPostExecute(JSONObject messagesStuff) { 

      int success = 0; // JSON Success tag 
      JSONArray messagesArray = null; 
      JSONObject message = null; 
      BroChatMsg broChatMsgObj = new BroChatMsg(); 
      // ArrayList<BroChatMsg> messagesList = new ArrayList<BroChatMsg>(); (use the adapter instead) 
      long timestamp; 
      String msgDate; 

      try { 
       success = messagesStuff.getInt(TAG_SUCCESS); 
      } catch (JSONException e) { 
       e.printStackTrace(); 
      } 

      if (success == 1) { 

       try { 
        messagesArray = messagesStuff.getJSONArray(TAG_MESSAGES); 
       } catch (JSONException e) { 
        e.printStackTrace(); 
       } 

       mAdapter.clear(); 

       for (int i = 0; i < messagesArray.length(); i++) { 

        //Populate the broChat object 
        try { 

         message = messagesArray.getJSONObject(i); 

         mQuickString = message.getString(TAG_SID); 
         broChatMsgObj.setSenderId(mQuickString); 

         mQuickString = message.getString(TAG_RID); 
         broChatMsgObj.setReceiverId(mQuickString); 

         mQuickString = message.getString(TAG_BODY); 
         mQuickString = mQuickString.replaceAll("\\r\\n", ""); 
         broChatMsgObj.setMsgBody(mQuickString); 

         mQuickString = message.getString(TAG_TIMESTAMP); 
         broChatMsgObj.setTimestampStr(mQuickString); 

         timestamp = Long.valueOf(mQuickString) * 1000; //Used to format date 
         broChatMsgObj.setTimestamp(timestamp); 

         Date msgTime = new Date(timestamp); 
         broChatMsgObj.setMsgTime(msgTime); 

         msgDate = new SimpleDateFormat("MM/dd/yy h:mm a").format(msgTime); 
         broChatMsgObj.setMsgDate(msgDate); 

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

        sBroChatMsg = broChatMsgObj; 

        Log.d("sBroChat Message: ", String.valueOf(i)); 
        Log.d("sBroChat SID ", sBroChatMsg.getSenderId()); 
        Log.d("sBroChat RID ", sBroChatMsg.getReceiverId()); 
        Log.d("sBroChat BODY ", sBroChatMsg.getMsgBody()); 
        Log.d("sBroChat TIMESTAMP ", sBroChatMsg.getMsgDate()); 

        mAdapter.add(sBroChatMsg); 
        // mAdapter.notifyDataSetChanged(); 

        // mRetrievedMessages.add(broChatMsgObj); 

        /* This is pretty much redundant. 
        for (i = 0; i < mRetrievedMessages.size(); i++) { 
         Log.d("message ", String.valueOf(i)); 
         Log.d("message ", mRetrievedMessages.get(i).getId().toString()); 
         Log.d("message TIMESTAMP ", mRetrievedMessages.get(i).getMsgDate()); 
         Log.d("message SID ", mRetrievedMessages.get(i).getSenderId()); 
         Log.d("message RID ", mRetrievedMessages.get(i).getReceiverId()); 
         Log.d("message BODY ", mRetrievedMessages.get(i).getMsgBody()); 
        } 
        */ 

       } // end message parsing 

       // sBroChat.setMessages(mRetrievedMessages); (no longer used) 

       // refresh the list view 
       mAdapter.notifyDataSetChanged(); 

      } else { 
       // no matching messages turned up 
       try { 
        mQuickString = messagesStuff.getString("message"); 
       } catch (JSONException e) { 
        e.printStackTrace(); 
       } 
       if (mQuickString == "Connection error") { 
        mConnectFailed = 1; 
       } 
      } 

      // return control to the main fragment 
      // onFetchBrofileTaskComplete.setFetchBrofileTaskComplete(); 
     } 
    } 

    @TargetApi(Build.VERSION_CODES.HONEYCOMB) 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle saveInstanceState) { 

     View v = inflater.inflate(R.layout.brochat_fragment, container, false); 
     /* This View holds the list and an edit window for new messages. 

     NOTE!: Nothing from the list is being inflated here! The adapter does all that. 
     */ 

     mLv = (ListView) v.findViewById(R.id.listView1); 
     mLv.setAdapter(mAdapter); 
     mLv.setEmptyView(v.findViewById(R.id.emptyElement)); 


     mNewMsgField = (EditText) v.findViewById(R.id.editText1); 
     mNewMsgField.setText(newMessageBody); 
     mNewMsgField.addTextChangedListener(new TextWatcher() { 
      @Override 
      public void beforeTextChanged(CharSequence c, int start, int before, int count) { 
       newMessageBody = c.toString(); 
      } 

      @Override 
      public void onTextChanged(CharSequence c, int start, int count, int after) { 
       // This method intentionally left blank 
      } 

      @Override 
      public void afterTextChanged(Editable c) { 
       // This one too 
      } 
     }); 

     mSendMessageBtn = (Button)v.findViewById(R.id.new_chat_msg_button); 
     mSendMessageBtn.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       // TODO: Prepare new message, check sending privilege, send if allowed. 
      } 
     }); 

     return v; 
    } 

    private class MessageAdapter extends ArrayAdapter<BroChatMsg> { 

     public MessageAdapter (ArrayList<BroChatMsg> chatter) { 
      super(getActivity(), 0, chatter); 
     } 

     @Override 
     public View getView(int position, View convertView, ViewGroup parent) { 
      // Displays one item at "position" 
      boolean isLoggedUser = false; // determines whether to show chat bubble on left or right 
      boolean hasPrevious = false; // false if this balloon is the oldest message 

      String dateStr = ""; 
      BroChatMsg last_bcm = new BroChatMsg(); 
      long prevTimeStamp = 0; 

      // If we weren't given a view, inflate one 
      if (convertView == null) { 
       convertView = getActivity().getLayoutInflater().inflate(R.layout.list_item_brochat, null); 
      } 

      // Configure the view for this message 
      BroChatMsg bcm = getItem(position); 
      if (position > 0) { hasPrevious = true; } 
      if (hasPrevious) { last_bcm = getItem(position - 1); } 
      if (bcm.getSid() == mCurrUserMemberId) {isLoggedUser = true; } 
      Date itemDate = bcm.getMsgTime(); 
      long itemTimestamp = bcm.getTimestamp(); 
      dateStr = new SimpleDateFormat("E, MMM dd, h:mm a").format(itemDate); 
      // don't print date if under 5 minutes since last message 
      if (hasPrevious) { 
       prevTimeStamp = last_bcm.getTimestamp(); 
       if ((itemTimestamp - prevTimeStamp) < 600000) { dateStr = "";} 
      } 
      TextView MsgTextView = (TextView)convertView.findViewById(R.id.comment); 
      TextView DateTextView = (TextView)convertView.findViewById(R.id.timelabel); 
      LinearLayout wrapper = (LinearLayout)convertView.findViewById(R.id.wrapper); 

      MsgTextView.setText(bcm.getMsgBody()); 
      DateTextView.setText(dateStr); 
      MsgTextView.setBackgroundResource(isLoggedUser ? R.drawable.bubble_yellow : R.drawable.bubble_green); 
      wrapper.setGravity(isLoggedUser ? Gravity.LEFT : Gravity.RIGHT); 

      return convertView; 
     } 

    } 

    @Override 
    public void onStart() { 
     super.onStart(); 

     if (mConnectFailed == 1) { 
      FragmentManager fm = getActivity().getSupportFragmentManager(); 
      CantConnectDialogFragment connectDialog = new CantConnectDialogFragment(); 
      connectDialog.show(fm, "Not connected"); 
     } 
    } 


} 
<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="vertical"> 

    <ListView 
     android:id="@+id/listView1" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:layout_centerVertical="true" 
     android:layout_above="@+id/form" 
     android:layout_alignParentLeft="true"> 
    </ListView> 

    <TextView 
     android:id="@+id/emptyElement" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:text="No messages" 
     android:textSize="24dp" 
     android:gravity="center_vertical|center_horizontal" /> 

    <RelativeLayout 
     android:id="@+id/form" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_alignParentBottom="true" 
     android:layout_alignParentLeft="true" 
     android:orientation="vertical"> 

     <EditText 
      android:id="@+id/editText1" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_alignParentLeft="true" 
      android:ems="10" 
      android:inputType="text" 
      android:layout_toLeftOf="@+id/new_chat_msg_button" 
      android:layout_toStartOf="@+id/new_chat_msg_button" /> 
     <Button 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:text="Send" 
      android:id="@+id/new_chat_msg_button" 
      android:layout_alignParentRight="true" /> 
    </RelativeLayout> 

</RelativeLayout> 
<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="vertical"> 

    <ListView 
     android:id="@+id/listView1" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:layout_centerVertical="true" 
     android:layout_above="@+id/form" 
     android:layout_alignParentLeft="true"> 
    </ListView> 

    <TextView 
     android:id="@+id/emptyElement" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:text="No messages" 
     android:textSize="24dp" 
     android:gravity="center_vertical|center_horizontal" /> 

    <RelativeLayout 
     android:id="@+id/form" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_alignParentBottom="true" 
     android:layout_alignParentLeft="true" 
     android:orientation="vertical"> 

     <EditText 
      android:id="@+id/editText1" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_alignParentLeft="true" 
      android:ems="10" 
      android:inputType="text" 
      android:layout_toLeftOf="@+id/new_chat_msg_button" 
      android:layout_toStartOf="@+id/new_chat_msg_button" /> 
     <Button 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:text="Send" 
      android:id="@+id/new_chat_msg_button" 
      android:layout_alignParentRight="true" /> 
    </RelativeLayout> 

</RelativeLayout> 

目前,正確的下載的郵件被顯示,但他們是從JSON結構檢索到的最後一個項目的所有副本。據我所知,XML佈局不是罪魁禍首。正在檢索的其他消息發生了什麼?

+0

請張貼它在做什麼,以及 –

+0

我還沒有看到brochatmsg類 –

+0

同樣圖片,請標註佈局 –

回答

0

在您的週期中,您正在使用相同的實例broChatMsgObj
所以所有項目都指向同一個對象的最後一個值。

for (int i = 0; i < messagesArray.length(); i++) { 

      //You have to create a new object 
      broChatMsgObj = new BroChatMsg(); 

      //Populate the broChat object 
      try { 

       message = messagesArray.getJSONObject(i); 

       mQuickString = message.getString(TAG_SID); 
       broChatMsgObj.setSenderId(mQuickString); 
       //.... 
       } 

     //.... 
    } 
+0

你釘了它:非常感謝。但是我仍然好奇爲什麼sBroChat總是顯示正確的值,但從未設法更改適配器中的數據。 –

+0

@BrogrammerDude不確定你的問題。你正在調用mAdapter.notifyDataSetChanged();只需更改適配器中的數據即可。 – Angela

相關問題