notifyDataSetChanged not working in android
The list view is not updating data when the notifyDataChanged() method called.
In onCreate() method i initialized the the listview with no data.
ListView videoList = (ListView)findViewById(R.id.videos_list);
videoList.setOnItemClickListener(listener);
listAdapter = new PHVideosListAdapter(PHVideosActivity.this, videos);
videoList.setAdapter(listAdapter);
After this I started fetching list of video using new VideosCategoryFetchTask().execute();
in the post execute method I called
@Override
protected void onPostExecute(Boolean success) {
if(success) {
listAdapter.notifyDataSetChanged();
} else {
//show dialog
}
}
but nothing is displayed on the list. If anybody knew the solution please help...
private class VideosDetailsFetchTask extends AsyncTask<String, Void, Boolean> {
@Override
public void onPreExecute() {
super.onPreExecute();
}
@Override
protected Boolean doInBackground(String... params) {
Boolean success = false;
try {
if (params.length >= 0) {
videos = (Videos)videoAPI.videosForCategoryId(params[0],new VideosParser());
success = true;
}
} catch (Exception e) {
// TODO: handle exception
}
return success;
}
@Override
protected void onPostExecute(Boolean success) {
if(success) {
progressBar.setVisibility(View.INVISIBLE);
onFinishVideoFetch();
} else {
//show dialog
}
}
}
here using two Async classes sec one is called on the onPostExecute() of first one..
private void onFinishVideoFetch() {
if(videos != null) {
listAdapter.notifyDataSetChanged();
}
}
I 'm not fetching videos one by one.. here a list of videos is returned....
After getting the list of videos i wanted to refresh the list.
@Override
protected void onProgressUpdate(Videos... values) {
videos = values[0];
//add published object to list which holds
listAdapter.notifyDataSetChanged();
}
I tried this but no luck please help..
this is the adapter class used
public class PHVideosListAdapter extends BaseAdapter{
private Videos videoTitles;
private LayoutInflater inflater;
public PHVideosListAdapter(Context context, Videos videoTitles) {
inflater = LayoutInflater.from(context);
this.videoTitles = videoTitles;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
if(videoTitles != null) {
return videoTitles.size();
}
else {
return 0;
}
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return videoTitles.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
VideoListViewHolder holder = null;
if (convertView == null) {
holder = new VideoListViewHolder();
convertView = inflater.inflate(R.layout.videos_list, null);
holder.videoTitle = (TextView) convertView.findViewById(R.id.video_title);
holder.videoImage = (ImageView) convertView.findViewById(R.id.video_image);
holder.videoDuration = (TextView) convertView.findViewById(R.id.video_duration);
convertView.setTag(holder);
} else {
holder = (VideoListViewHo开发者_C百科lder)convertView.getTag();
}
holder.videoImage.setImageResource(R.drawable.icon);
holder.videoDuration.setText("00:10");
holder.videoTitle.setText(videoTitles.get(position).getVideoTitle());
return convertView;
}
private class VideoListViewHolder {
ImageView videoImage;
TextView videoTitle;
TextView videoDuration;
}
}
When you first create your PHVideosListAdapter
, it is holding a reference to the Videos
list that I assume is a member of your Activity. In your doInBackground
method, the call to videoAPI.videosForCategoryId
is updating the Videos
reference in your Activity, but the adapter is still holding the original reference that was passed in to the constructor for PHVideosListAdapter
. You need to either recreate the PHVideosListAdapter
in onPostExecute
or add a set method in PHVideosListAdapter
to change the private variable videoTitles
.
I ran into the same issue with using the ArrayAdapter
provided by Google. You can only set the underlying List
in the constructor, so you must recreate the ArrayAdapter or create your own class that allows changing of the underlying data for notifyDataSetChanged
to work.
You need to override onProgressUpdate()
of AsynTask class
Heres an example of AsyncTask assuming your list is videos
which holds Objects of type Video
and your extended adapter is VideosAdapter
private class VideosDetailsFetchTask extends AsyncTask<String, Video, Boolean> {
@Override
public void onPreExecute() {
super.onPreExecute();
}
@Override
protected Boolean doInBackground(String... params) {
//utilize string you are passing otherwise use Void as first generic param.
Boolean success = false;
try {
if (params.length >= 0) {
Videos videoFetched = (Videos)PrimeraHoraAPI.videosForCategoryId(params[0],new VideosParser());
success = true;
publishProgress(videoFetched);
}
} catch (Exception e) {
// TODO: handle exception
}
return success;
}
@Override
protected void onPostExecute(Boolean success) {
if(success) {
progressBar.setVisibility(View.INVISIBLE);
onFinishVideoFetch();
} else {
//show dialog
}
}
@Override
protected void onProgressUpdate(Video... values) {
videos.add(values[0]);//add published object to list which holds
((VideosAdapter)getListAdapter()).notifyDataSetChanged();
}
}
It's not very good descript anywhere but what you do when u call
listAdapter.notifyDataSetChanged();
u tell your machine "oke, your code is not legit" and now u stop! so basically ur machine has no clue what 2 do next! My solution is:
create a private void setupData()
private void setupData() {
ArrayList<HashMap<String,String>> list = new ArrayList<HashMap<String,String>>();
final List<Table_Follow> data = db.getAllData(); // from database
HashMap<String,String> item;
for(Table_Data td : data){
item = new HashMap<String,String>();
item.put("name1", td.getName_One());
item.put("name2", td.getName_Two());
item.put("date", td.getDate());
list.add(item);
};
my_data = new SimpleAdapter(this, list, R.layout.my_listview_row, new String[] { "name1","name2", "date" }, new int[] {R.id.lv_line_a, R.id.lv_line_b, R.id.lv_line_c});
listview.setAdapter(my_data);
}
I have a custom layout with 3 textviews (line a > title, line b > subtitle, line c > time see bottom page for xml). So basicly i ll use this private void to tell my machine what 2 do next by using setupData() after calling > notifydatasetchanged() in my main thread
my_data.notifyDataSetChanged();
setupData();
One last thing! I use the android listview id for my listview in my main xml file! Oh and if you have trouble using your 'onItemClickListener' (not giving u the right id, just text me! I faced that problem and solved it pretty shitty but it works :p)
My xml file for my listview:
<?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="wrap_content" >
<TextView
android:id="@+id/lv_line_c"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:textSize="15sp" />
<LinearLayout
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="@+id/lv_line_a"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:textSize="24sp"
android:textStyle="bold" />
<TextView
android:id="@+id/lv_line_b"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:textSize="15sp" />
</LinearLayout>
</RelativeLayout>
精彩评论