Giang T Giang T - 1 month ago 5
Android Question

The ArrayList is zero when setAdapter

This is my Activity:

public class HomeTimelineActivity extends AppCompatActivity {
private TwitterClient client;
Context mContext;
@BindView(R.id.rvTweets)
RecyclerView rvTweets;
List<Tweet> mTweets;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home_timeline);
Butterknife.bind(this);
client = TwitterApplication.getRestClient();
populateTimeline();
}

private void populateTimeline() {
client.getHomeTimeline(new JsonHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers, JSONArray jsonArray) {
Log.d("DEBUG", jsonArray.toString());

mTweets = new ArrayList<Tweet>();

for (int i = 0; i < jsonArray.length(); i++) {
try {
JSONObject jsonTweet = jsonArray.getJSONObject(i);
Tweet tweet = new Tweet();
tweet.setBody(jsonTweet.getString("text"));
tweet.setUid(jsonTweet.getLong("id"));
tweet.setCreateAt(jsonTweet.getString("created_at"));
JSONObject jsonUser = jsonTweet.getJSONObject("user");
User user = new User();
user.setName(jsonUser.getString("name"));
user.setUid(jsonUser.getLong("id"));
user.setScreenname(jsonUser.getString("screen_name"));
user.setProfileImageurl(jsonUser.getString("profile_image_url"));
tweet.setUser(user);

mTweets.add(tweet);

runOnUiThread(new Runnable() {
@Override
public void run() {
TweetAdapter adapter = new TweetAdapter(mContext, mTweets);
rvTweets.setAdapter(adapter);

RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(mContext);
rvTweets.setLayoutManager(layoutManager);

}
});


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

}


@Override
public void onFailure(int statusCode, Header[] headers, Throwable throwable, JSONArray errorResponse) {
Log.d("DEBUT", errorResponse.toString());
}
});
}
}


This is my Adapter:

public class TweetAdapter extends RecyclerView.Adapter<TweetAdapter.TweetViewHolder>{
private Context mContext;
private List<Tweet> mTweets;

// Automatically add the Constructor here

public TweetAdapter(Context context, List<Tweet> tweets) {
mContext = context;
mTweets = tweets;
}


// Implements compulsory methods

@Override
public TweetViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.tweet_list_items,
parent, false);
TweetViewHolder viewHolder = new TweetViewHolder(view);

return viewHolder;
}


@Override
public void onBindViewHolder(TweetViewHolder holder, int position) {
holder.bindModel(mTweets.get(position));
}

@Override
public int getItemCount() {
return mTweets.size();
}

public class TweetViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
// Hook the ID to new created Widget using ButterKnife
@BindView(R.id.imgUserProfile)
ImageView userProfile;
@BindView(R.id.tvUserName)
TextView userName;
@BindView(R.id.tvTweet)
TextView tweetText;

TweetViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);

// Set the OnclickListener of an item in list
itemView.setOnClickListener(this);
}


void bindModel(Tweet tweet) {
// Use the Widget mVar and the model name to set_get info
tweetText.setText(tweet.getBody());
}

@Override
public void onClick(View view) {
// Add What happen with OnClick


}
}

}


I try to set the Adapter with the mTweets List. I used debugger to make sure that the getTweet method has returned enough Object
tweets = {ArrayList@5524} size = 25

0 = {Tweet@5530}
1 = {Tweet@5531}
2 = {Tweet@5532}
3 = {Tweet@5533}
4 = {Tweet@5534}
5 = {Tweet@5535}
6 = {Tweet@5536}
7 = {Tweet@5537}
8 = {Tweet@5538}
9 = {Tweet@5539}
10 = {Tweet@5540}
11 = {Tweet@5541}


However, when I try to set the Adapter, there is no data displayed and the app immediately stopped. Strange, the Logcat is blank without any information. It's simply black. The authentication with Twitter worked.
Anyone please help me with this.

Answer

There are some steps you need to follow to improve your code performance and get it up and running.

The main thing which you are missing is that you are setting the mTweets after every iteration in the loop. You should set mTweets in the Adapter only after the entire list is populated. Following that, you should call adapter notifyDataSetChanged().

Follow these:

step 1

 // Class variable adapter...
 private TweetAdapter adapter;

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home_timeline);

        client = TwitterApplication.getRestClient();

        // Initially pass null as the mTweets since you don't have any tweets right now...
        adapter = new TweetAdapter(mContext, null);
        rvTweets.setAdapter(adapter);

        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(mContext);

        rvTweets.setLayoutManager(layoutManager);
        populateTimeline();
    }

step 2 In your TweetAdapter, modify getItemCount method to handle the null checks on mTweets. Add a new Method addNewTweets to your Adapter.

   @Override
    public int getItemCount() {
        return (mTweets !=null) ? mTweets.size() : 0;
    }

    public void setNewTweets(List<Tweet> newTweetList) {
        this.mTweets = newTweetList;
    }

step 3 Modify this method populateTimeline

private void populateTimeline() {
        client.getHomeTimeline(new JsonHttpResponseHandler() {
            @Override
            public void onSuccess(int statusCode, Header[] headers, JSONArray jsonArray) {
                Log.d("DEBUG", jsonArray.toString());

                mTweets = new ArrayList<Tweet>();

                    for (int i = 0; i < jsonArray.length(); i++) {
                        try {
                            JSONObject jsonTweet = jsonArray.getJSONObject(i);
                            Tweet tweet = new Tweet();
                            tweet.setBody(jsonTweet.getString("text"));
                            tweet.setUid(jsonTweet.getLong("id"));
                            tweet.setCreateAt(jsonTweet.getString("created_at"));
                            JSONObject jsonUser = jsonTweet.getJSONObject("user");
                            User user = new User();
                            user.setName(jsonUser.getString("name"));
                            user.setUid(jsonUser.getLong("id"));
                            user.setScreenname(jsonUser.getString("screen_name"));
                            user.setProfileImageurl(jsonUser.getString("profile_image_url"));
                            tweet.setUser(user);

                            mTweets.add(tweet);


    /*  REMOVE THIS CODE!    
                                    runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            TweetAdapter adapter = new TweetAdapter(mContext, mTweets);
                                            rvTweets.setAdapter(adapter);

                                            RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(mContext);
                                            rvTweets.setLayoutManager(layoutManager);

                                        }
                                    });
        */

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

           // NOW SET MTWEETS IN YOUR ADAPTER.
           // NOTIFY the adapter that the data is changed.

           adapter.setNewTweets(mTweets);
           adapter.notifyDataSetChanged();

        }

    }
Comments