繁体   English   中英

调用notifyDataSetChanged时,带有customAdapter的ListView是否未更新?

[英]ListView with customAdapter not updated when notifyDataSetChanged is called?

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

问题:如何在调用adAdapter.notifyDataSetChanged();时使列表视图反映新数据,为什么不更新它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的构造函数

 // 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:

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();
        }
    }
}

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

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

看起来如何?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM