2016-09-25 46 views
0

getView加載數據()方法的Android - ListView的getView()等待返回,直到從火力

public View getView(final int position, View convertView, ViewGroup parent) { 
    View view; 

    if(convertView != null){ 
     view = convertView; 
    }else{ 
     view = View.inflate(context, resLayout, null); 
    } 

    CircleImageView ivProfile = (CircleImageView) view.findViewById(R.id.ivProfile); 
    tvName = (TextView) view.findViewById(R.id.tvName); 
    tvMessage = (TextView) view.findViewById(R.id.tvLastMessage); 
    tvDate = (TextView) view.findViewById(R.id.tvDate); 

    setData(position); 

    return view; 
} 

使用setData(位置)

private void setData(final int position){ 
    Query query_user = FirebaseDatabase.getInstance().getReference().child("Users"). 
      orderByChild("email"). 
      equalTo(listOfRooms.get(position).getRecipient()); 

    query_user.addChildEventListener(new ChildEventListener() { 
     @Override 
     public void onChildAdded(DataSnapshot dataSnapshot, String s) { 
      name = dataSnapshot.child("name").getValue().toString(); 

      //Log.d("LOG_ROOM", String.valueOf(listOfRooms.size() + "||" + position)); 
      //Log.d("LOG_ROOM", tvName.getText().toString() + "||" + tvMessage.getText().toString() + "||" + tvDate.getText().toString()); 

      tvName.setText(name); 
      tvMessage.setText(listOfRooms.get(position).getListOfMessages().get(listOfRooms.get(position).getListOfMessages().size() - 1).getMessage()); 
      tvDate.setText(convertTimestampIntoDate(listOfRooms.get(position).getListOfMessages(). 
        get(listOfRooms.get(position).getListOfMessages().size() -1).getTimestamp())); 

      Log.d("LOG_FUNCTION", "onChildAdded Called" + ": " + name); 
     } 

     @Override 
     public void onChildChanged(DataSnapshot dataSnapshot, String s) { 

     } 

     @Override 
     public void onChildRemoved(DataSnapshot dataSnapshot) { 

     } 

     @Override 
     public void onChildMoved(DataSnapshot dataSnapshot, String s) { 

     } 

     @Override 
     public void onCancelled(DatabaseError databaseError) { 

     } 
    }); 
} 

我想設置數據到listView的每個項目,但是當您看到setData(int)的方法時,該方法將處理任務UI;它會設置用戶名,消息和日期的textview文本。但是,我發現這種編碼存在問題。例如,有兩個數據可以從服務器加載,但在加載數據時在onChildAdded()方法中,getView()的方法返回view,因此只有最後一項listView發生更改。 有沒有可能的方法來補充這種問題?

the result

+0

你應該創建一個基於位置的獨特addChildEventListener。現在它覆蓋以前的位置並在最後一個項目加載。 – Jai

回答

0

使用處理器等待從火力

// construct the handler inside your adapter's constructor so you know it is on the UI thread 
    Handler myHandler = new Handler(); 

class LoadData implements Runnable { 
    TextView tvName, tvMessage, tvDate; 
    int position; 

public LoadData(TextView tvName, TextView tvMessage, TextView tvDate, int position) { 
    this.tvName = tvName; 
    this.tvMessage = tvMessage; 
    this.tvDate = tvDate; 
    this.position = position; 
} 

@Override 
public void run() { 

    // keep your Set data stuff her and pass reference of your textviews 
    setData(position, tvName, tvDate, tvMessage); 

} 
} 

這裏重要的東西中獲取數據,這是更好的做法是始終使用holder類的getView方法,而不是膨脹你的看法每次調用getView都可能導致性能問題:

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

final ViewHolder viewHolder; 
View view = convertView; 

if(view != null){ 
    //view = convertView; 
    viewHolder = (ViewHolder) view.getTag(); 
    //Change is here 
    myHandler.removeCallbacks(viewHolder.mRunnable); 
}else{ 
    //view = View.inflate(context, resLayout, null); 
    view = LayoutInflater.from(mContext).inflate(resLayout, parent, false); 
    viewHolder.ivProfile = (CircleImageView) view.findViewById(R.id.ivProfile); 
    viewHolder.tvName = (TextView) view.findViewById(R.id.tvName); 
    viewHolder.tvMessage = (TextView) view.findViewById(R.id.tvLastMessage); 
    viewHolder.tvDate = (TextView) view.findViewById(R.id.tvDate); 
    //Change is here 
    viewHolder.mRunnable = new LoadData(viewHolder.tvName, viewHolder.tvMessage, viewHolder.tvDate, position); 
} 

//setData(position); 
//Change is here 
myHandler.postDelayed(viewHolder.mRunnable, 3000); 

return view; 
} 

而且你的holder類會是這樣這將是你的適配器類的子類:

private static class ViewHolder { 
    CircleImageView ivProfile; 
    TextView tvName, tvMessage, tvDate; 
} 
+0

非常感謝你 – MyNameIsAsker

+0

@MyNameIsAsker:永遠歡迎! :) – Jai

0

setData(position);把它在後臺線程。

public View getView(final int position, View convertView, ViewGroup parent) { 
    View view; 

    if(convertView != null){ 
     view = convertView; 
    }else{ 
     view = View.inflate(context, resLayout, null); 
    } 

    CircleImageView ivProfile = (CircleImageView) view.findViewById(R.id.ivProfile); 
    tvName = (TextView) view.findViewById(R.id.tvName); 
    tvMessage = (TextView) view.findViewById(R.id.tvLastMessage); 
    tvDate = (TextView) view.findViewById(R.id.tvDate); 

    //setData(position); 
    new SetInBackAsyncTask(position).execute(); 

    return view; 
    } 

class SetInBackAsyncTask extends AsyncTask<String, String, String> { 

    int pos; 
    SetInBackAsyncTask(int pos){ 
     this.pos =pos; 
     } 
    protected void OnPreExecute(){} 
    protected String doInBackground(String... params) { 
     setData(pos); 
    } 
    protected void onPostExecute(String file_url) { } 
} 
+0

我不認爲這個UI線程可以被doInBackground() – MyNameIsAsker

+0

@MyNameIsAsker訪問,當設置值時使用'runOnUiThread'設置它們在'onPost.' –