调用notifyDataSetChanged时,带有customAdapter的ListView是否未更新? [英] ListView with customAdapter not updated when notifyDataSetChanged is called?

查看:62
本文介绍了调用notifyDataSetChanged时,带有customAdapter的ListView是否未更新?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有两个适配器的Listview.他们收到一个包含一些数据的数组,当滚动到列表视图的底部时,更多的数据将被加载到该数组中,列表视图应在此处添加新数据.

I have a Listview with two adapters. They receive an Array with some data and when scrolled to bottom of the listview more data is loaded into the Array and here the listview should add the new data.

问题: 如何在调用adAdapter.notifyDataSetChanged();时使列表视图反映新数据以及为什么不更新呢?

Question: How can I make the listview reflect the new data and why isn't it updated when I call adAdapter.notifyDataSetChanged(); ?

将我下载数据的内部类片段化&在onPostExecute中更新UI:

@Override
    protected void onPostExecute(String result) {

        super.onPostExecute(result);

        numberofpagesshown = numberofpagesshown + 1;

        if(numberofpagesshown == 1 ) {

            list = (ListView) getActivity().findViewById(R.id.search_listview_movie);

            adapter = new SearchListViewAdapter(getActivity(), mylist);

            adAdapter = new BannerAdListView2(getActivity(), adapter);

           // list.setAdapter(adapter); this works when adapter.notifyDataSetChanged(); also is in the else statement but here I don't use the BannerAdListView2 adapter which i want to?

list.setAdapter(adAdapter);

            bar.setVisibility(View.GONE);
        }
        else {

          //  adapter.notifyDataSetChanged();   // Here the listview should get refresh with the new data

              adAdapter.notifyDataSetChanged();

            bar.setVisibility(View.GONE);

        }


        // Attach the listener to the AdapterView onCreate
        list.setOnScrollListener(new EndlessScrollListener() {
            @Override
            public void onLoadMore(int page, int totalItemsCount) {
                // Triggered only when new data needs to be appended to the list
                // Append new items to AdapterView
                if(pageNumberInt < totalPagesInt){

                   ++incre;
                   new DownloadJSON().execute();
                }

            }
        });


    }

这是我的SearchListViewAdapter:

public class SearchListViewAdapter extends BaseAdapter{

Context context;
ArrayList<HashMap<String, String>> data;
HashMap<String, String> mylist = new HashMap<>();


static String url;
static String title;

public SearchListViewAdapter(Context a, ArrayList<HashMap<String, String>> d) {
    context = a;
    data = d;
}

public int getCount() {
    return data.size();
}

public HashMap<String, String> getItem(int position) {
    return data.get(position);
}

public long getItemId(int position) {
    return position;
}

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

    // Avoid unneccessary calls to findViewById() on each row
    final ViewHolder holder;

    /*
     * If convertView is not null, reuse it directly, no inflation
     * Only inflate a new View when the convertView is null.
     */

        if (convertView == null) {
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.search_list_item, parent, false);

            holder = new ViewHolder();

            holder.poster = (ImageView) convertView.findViewById(R.id.list_image);

            holder.textForTitle = (TextView) convertView.findViewById(R.id.search_title);

            holder.textForTitle.setTag(position);

            convertView.setTag(holder);
        }
        else{

            // Get the ViewHolder back to get fast access to the TextView
            // and the ImageView.
            holder = (ViewHolder) convertView.getTag();
            holder.textForTitle.setTag(data.get(position));
        }



        mylist = data.get(position);


        final String mediaType = mylist.get("media_type");

        if (mediaType.equals("movie")) {

            String posterPath = mylist.get("poster_path");
            url = "http://image.tmdb.org/t/p/w185" + posterPath;
            title = mylist.get("title");
        } else if (mediaType.equals("tv")) {

            String posterPath = mylist.get("poster_path");
            url = "http://image.tmdb.org/t/p/w185" + posterPath;
            title = mylist.get("original_name");
        } else {

            String posterPath = mylist.get("profile_path");
            url = "http://image.tmdb.org/t/p/w185" + posterPath;
            title = mylist.get("name");

        }


        // set image url correctly
        // sizes for image 45, 92, 154, 185, 300, 500


        // load image url into poster
        Picasso.with(context).load(url).into(holder.poster);

        // set title to textview

        holder.textForTitle.setText(title);





    return convertView;


}



class ViewHolder {
    ImageView poster;
    TextView textForTitle;
}

 }

和我的BannerAdListView2适配器:

public class BannerAdListView2 extends BaseAdapter
     {

Activity activity;
Context context;
BaseAdapter delegate;
int k = 7;
int baseItems;
int noAds;



// Constructor takes in a BaseAdapter
public BannerAdListView2(Activity activity, BaseAdapter delegate ) {

    this.activity = activity;
    this.delegate = delegate;

    baseItems = delegate.getCount();
    noAds  = baseItems / k;
    LayoutInflater mLayoutInflater = (LayoutInflater) this.activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

}


         @Override
         public int getCount() {
             // Total count includes list items and ads.
             return baseItems + noAds;
         }

         @Override
         public Object getItem(int position) {
             // Return null if an item is an ad.  Otherwise return the delegate item.
             if (isItemAnAd(position)) {
                 return null;
             }
             return delegate.getItem(getOffsetPosition(position));
         }

         @Override
         public long getItemId(int position) {
             return position;
         }

         @Override
         public int getViewTypeCount() {
             return delegate.getViewTypeCount() + noAds;
         }

         @Override
         public int getItemViewType(int position) {
             if (isItemAnAd(position)) {
                 return delegate.getViewTypeCount();
             } else {
                 return delegate.getItemViewType(getOffsetPosition(position));
             }
         }

         @Override
         public boolean areAllItemsEnabled() {
             return false;
         }

         @Override
         public boolean isEnabled(int position) {
             return (!isItemAnAd(position)) && delegate.isEnabled(getOffsetPosition(position));
         }

         private boolean isItemAnAd(int position) {


             if (position < k) return false;
             // Calculate current offset caused by ads already embedded

             if (position==k){
                 return true;
             }
             else {
                 return isItemAnAd(position-k);
             }


         }

         // Get the position that is offset by the insertion of the ads
         private int getOffsetPosition(int position) {
             int currentNoAds = position / k;
             return position - currentNoAds;

         }



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

             // Display every n list items
             if (isItemAnAd(position)) {
                 if (convertView instanceof AdView) {
                     // Don’t instantiate new AdView, reuse old one
                     return convertView;
                 } else {
                     // Create a new AdView
                     AdView adView = new AdView(activity);
                     adView.setAdSize(AdSize.BANNER);
                     String bannerId = "My unit id";
                     adView.setAdUnitId(bannerId);

                     // Disable focus for sub-views of the AdView to avoid problems with
                     // trackpad navigation of the list.
                     for (int i = 0; i < adView.getChildCount(); i++)
                     {
                         adView.getChildAt(i).setFocusable(false);
                     }
                     adView.setFocusable(false);

                     // Convert the default layout parameters so that they play nice with
                     // ListView.

                     float density = activity.getResources().getDisplayMetrics().density;
                     int height = Math.round(AdSize.BANNER.getHeight() * density);
                     AbsListView.LayoutParams params = new AbsListView.LayoutParams(
                             AbsListView.LayoutParams.MATCH_PARENT,
                             height);
                     adView.setLayoutParams(params);
                     AdRequest bannerIntermediateReq = new AdRequest.Builder()
                             .addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
                             .addTestDevice("d9e108ab") //means that a test ad is shown on my phone
                             .build();

                     adView.loadAd(bannerIntermediateReq);

                     return adView;
                 }
             } else {

                 // Offload displaying other items to the delegate
                 return delegate.getView(getOffsetPosition(position) ,
                         convertView, parent);

             }
         }
     }

修改: 更改了BannerAdListView2的构造函数

Changed the constructor of BannerAdListView2

 // Constructor takes in a BaseAdapter
public BannerAdListView2(Activity activity, final BaseAdapter delegate ) {

    this.activity = activity;
    this.delegate = delegate;
    delegate.registerDataSetObserver(new DataSetObserver() {
        public void onChanged() {
            baseItems = delegate.getCount();
            noAds = baseItems / k;
        }

        public void onInvalidated() {
            notifyDataSetInvalidated();
        }
    });
    baseItems = delegate.getCount();
    noAds  = baseItems / k;
    LayoutInflater mLayoutInflater = (LayoutInflater) this.activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

}

然后是片段

@Override
    protected void onPostExecute(String result) {

        super.onPostExecute(result);

        numberofpagesshown = numberofpagesshown + 1;

        if(numberofpagesshown == 1 ) {

            list = (ListView) getActivity().findViewById(R.id.search_listview_movie);

            adapter = new SearchListViewAdapter(getActivity(), mylist);

            adAdapter = new BannerAdListView2(getActivity(), adapter);

            list.setAdapter(adAdapter);

            bar.setVisibility(View.GONE);
        }
        else {

            adapter.notifyDataSetChanged();   

            bar.setVisibility(View.GONE);

        }

     }

推荐答案

尝试此解决方案... DecorerAdapter:

Try this solution ... DecorerAdapter:

public static abstract class DecorerAdapter extends BaseAdapter {

            public int DECORER_ITEM_TYPE;
            private final BaseAdapter mInnerAdapter;
            private final int mRepeatAfterEvery;
            private int mCount;

            public DecorerAdapter(BaseAdapter innerAdapter, int repeatAfterEvery) {
                mInnerAdapter = innerAdapter;
                mRepeatAfterEvery = repeatAfterEvery;
                mInnerAdapter.registerDataSetObserver(new DataSetObserver() {
                    @Override
                    public void onChanged() {
                        notifyDataSetChanged();
                    }

                    @Override
                    public void onInvalidated() {
                        notifyDataSetInvalidated();
                    }
                });
                setupAdapter();
            }

            @Override
            public void notifyDataSetChanged() {
                setupAdapter();
                super.notifyDataSetChanged();
            }

            private void setupAdapter(){
                mCount = mInnerAdapter.getCount();
                mCount += (mCount  + mRepeatAfterEvery - 2) / (mRepeatAfterEvery - 1);
                DECORER_ITEM_TYPE = mInnerAdapter.getViewTypeCount();
            }

            @Override
            public int getCount() {
                return mCount;
            }

            @Override
            public Object getItem(int position) {
                if(position % mRepeatAfterEvery == 0)
                    return null;
                return mInnerAdapter.getItem(calculateInnerPosition(position));
            }

            private int calculateInnerPosition(int position) {
                return position - (position  + mRepeatAfterEvery - 1) / mRepeatAfterEvery;
            }

            @Override
            public long getItemId(int position) {
                if(position % mRepeatAfterEvery == 0)
                    return -1;
                return mInnerAdapter.getItemId(calculateInnerPosition(position));
            }

            @Override
            public int getItemViewType(int position) {
                if(position % mRepeatAfterEvery == 0)
                    return DECORER_ITEM_TYPE;
                return mInnerAdapter.getItemViewType(calculateInnerPosition(position));
            }

            @Override
            public boolean hasStableIds() {
                return mInnerAdapter.hasStableIds();
            }

            @Override
            public int getViewTypeCount() {
                return mInnerAdapter.getViewTypeCount() + 1;
            }

            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                if(position % mRepeatAfterEvery == 0)
                    return getDecorerView((position  + mRepeatAfterEvery - 1) / mRepeatAfterEvery, convertView, parent);
                return mInnerAdapter.getView(calculateInnerPosition( position), convertView, parent);
            }

            public abstract View getDecorerView(int position, View convertView, ViewGroup parent);
        }

使用代码:

package pl.selvin.decoreradapter;

import android.database.DataSetObserver;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;

public class MainActivity extends AppCompatActivity {

    /*** paste the DecorerAdapter class here ***/

    public static class MyListFragment extends ListFragment{
        final ArrayList<String> strings = new ArrayList<>();
        private BaseAdapter innerAdapter;

        @Override
        public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
            menu.add("Add rnd(10) more");

            super.onCreateOptionsMenu(menu, inflater);
        }

        final Random rnd = new Random();
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            final String[] toAdd = new String[rnd.nextInt(10)];
            int start = strings.size();
            for(int i = 0; i < toAdd.length; i++)
                toAdd[i] = (start + i) + "";
            Collections.addAll(strings, toAdd);
            Toast.makeText(getActivity(), "Added " + toAdd.length + " count: " + strings.size(), Toast.LENGTH_SHORT).show();
            innerAdapter.notifyDataSetChanged();
            return true;
        }

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setHasOptionsMenu(true);
            for(int i = 0; i < 4; i++) {
                strings.add(i + "");
            }
            innerAdapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1, strings);
            setListAdapter(new DecorerAdapter(innerAdapter, 5) {
                @Override
                public View getDecorerView(int position, View convertView, ViewGroup parent) {
                    if(convertView == null) {
                        convertView = new TextView(getActivity());
                        convertView.setBackgroundColor(Color.RED);
                    }
                    ((TextView)convertView).setText("AdView: " + position);
                    return convertView;
                }
            });
        }

        @Override
        public void onListItemClick(ListView l, View v, int position, long id) {
            String item = (String)l.getItemAtPosition(position);
            Toast.makeText(getActivity(), "Item click: " + (item == null ? "ADVIEW" : item), Toast.LENGTH_LONG).show();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction().replace(android.R.id.content, new MyListFragment(), "LIST").commit();
        }
    }
}

它在传递给构造函数的每个元素上重复装饰器视图...

It repeats decorer view at every element passed to the constructor ...

您所需要做的就是以与普通适配器中的getView相似的方式实现getDecorerView

all you need to do is implement getDecorerView in the similar way as getView in normal adapter

这篇关于调用notifyDataSetChanged时,带有customAdapter的ListView是否未更新?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆