我有一个带有两个适配器的Listview。它们接收带有一些数据的数组,当滚动到列表视图的底部时,更多数据被加载到数组中,这里列表视图应该添加新数据。
问题:
如何让列表视图反映新数据以及为什么在我致电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);
}
}
答案 0 :(得分:1)
尝试此解决方案...... 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();
}
}
}
它在传递给构造函数的每个元素上重复decorer视图......
您需要做的就是以与普通适配器中的getView类似的方式实现getDecorerView