我使用过ListView并将自定义的ArrayAdapter绑定到它
将setOnItemClickListener(...)绑定到它。
还有2个按钮,'next'和'previous'。点击每个按钮,我调用一个webservice,根据收到的响应,我更新了适配器(并期望ListView得到更新。)
我的问题是,经过几次下次和之前的点击后,Touch无法在ListView上运行。
花了很多时间搞清楚,请帮帮我。 我的一个发现是:通常观察到GC后出现问题。
布局代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/background"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/layout1"
style="@style/TitleBar"
android:background="@drawable/top_bg" >
<TextView
android:id="@+id/search_result_titleTxt"
style="@style/TitleBarText"
android:paddingLeft="8dip"
android:text="@string/title_restaurants" />
<ImageView
android:id="@+id/sep"
android:layout_width="1px"
android:layout_height="fill_parent"
android:layout_marginRight="7dip"
android:background="@drawable/seprator_img" />
<ImageView
android:id="@+id/img1"
style="@style/TitleBarLogo"
android:background="@null"
android:onClick="onMapClick"
android:src="@drawable/map" />
<ImageView
android:id="@+id/filterSep"
android:layout_width="1px"
android:layout_height="fill_parent"
android:layout_marginRight="7dip"
android:background="@drawable/seprator_img" />
<ImageView
android:id="@+id/filter"
style="@style/TitleBarLogo"
android:background="@null"
android:onClick="onSearchClick"
android:src="@drawable/filter" />
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/background"
android:padding="6dip" >
<LinearLayout
android:id="@+id/search_contentView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="@+id/search_result_countTxt"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:focusable="false"
android:text="@string/total_restaurants"
android:textColor="#ffffff"
android:visibility="gone" />
<ListView
android:id="@+id/search_result_list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@layout/customshape_table"
android:cacheColorHint="#00000000"
android:divider="#BAC698"
android:dividerHeight="2px"
android:paddingLeft="4dip"
android:paddingRight="4dip"
android:scrollbars="none" />
<LinearLayout
android:id="@+id/layout1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginTop="5dp" >
<ImageView
android:id="@+id/search_result_prevBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:layout_weight="1"
android:background="@null"
android:onClick="onPrevBtnClick"
android:src="@drawable/previous_btn"
android:visibility="gone" />
<ImageView
android:id="@+id/search_result_nextBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_weight="1"
android:background="@null"
android:gravity="right"
android:onClick="onNextBtnClick"
android:src="@drawable/next_btn"
android:visibility="gone" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<HorizontalScrollView
android:id="@+id/bottomBar"
android:layout_width="fill_parent"
android:layout_height="55dip"
android:layout_alignParentBottom="true"
android:background="@drawable/bottom_bar"
android:scrollbarSize="2dip"
android:scrollbarThumbHorizontal="@drawable/scrollbar_horizontal_thumb"
android:scrollbarTrackHorizontal="@drawable/scrollbar_horizontal_track" >
<LinearLayout
...
</LinearLayout>
</HorizontalScrollView>
适配器代码:
public class LazyListAdapter extends ArrayAdapter<Resturant> {
private ArrayList<Resturant> resturants;
public ImageLoader imageLoader;
Context context;
int layoutResourceId;
public LazyListAdapter(Context context, int layoutResourceId,
ArrayList<Resturant> resturants) {
super(context, layoutResourceId, resturants);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.resturants = resturants;
imageLoader = new ImageLoader(context);
setNotifyOnChange(true);
}
public static class ViewHolder {
public TextView restaurantName;
public TextView address;
public TextView completeAddress;
public TextView cuisines;
public ImageView image;
ImageView offerImg;
ImageView freqImg;
TextView dinnerCountImg;
ImageView friDashImg;
ImageView friEveDashImg;
ImageView satDashImg;
ImageView satEveDashImg;
ImageView sunDashImg;
ImageView sunEveDashImg;
ImageView callImg;
TextView metricTxt;
TextView distanceTxt;
View overlay;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
ViewHolder holder;
if (convertView == null) {
System.out.println("pos:::::::::: " + position);
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
vi = inflater.inflate(layoutResourceId, parent, false);
holder = new ViewHolder();
holder.restaurantName = (TextView) vi
.findViewById(R.id.search_item_restTitleTxt);
holder.address = (TextView) vi
.findViewById(R.id.search_item_addTxt);
holder.completeAddress = (TextView) vi
.findViewById(R.id.search_item_complete_addTxt);
holder.cuisines = (TextView) vi
.findViewById(R.id.search_item_cuisineTxt);
holder.image = (ImageView) vi.findViewById(R.id.search_item_image);
holder.offerImg = (ImageView) vi
.findViewById(R.id.search_item_specialOfferImg);
holder.freqImg = (ImageView) vi
.findViewById(R.id.search_item_frequencyImg);
holder.dinnerCountImg = (TextView) vi
.findViewById(R.id.search_item_dinnerCountTxt);
holder.friDashImg = (ImageView) vi
.findViewById(R.id.search_item_friDashImg);
holder.friEveDashImg = (ImageView) vi
.findViewById(R.id.search_item_friDashEveImg);
holder.satDashImg = (ImageView) vi
.findViewById(R.id.search_item_satDashImg);
holder.satEveDashImg = (ImageView) vi
.findViewById(R.id.search_item_satDashEveImg);
holder.sunDashImg = (ImageView) vi
.findViewById(R.id.search_item_sunDashImg);
holder.sunEveDashImg = (ImageView) vi
.findViewById(R.id.search_item_sunDashEveImg);
holder.callImg = (ImageView) vi
.findViewById(R.id.search_item_callImg);
holder.metricTxt = (TextView) vi
.findViewById(R.id.search_item_metricTxt);
holder.distanceTxt = (TextView) vi
.findViewById(R.id.search_item_distanceTxt);
holder.overlay = vi.findViewById(R.id.overlay);
vi.setTag(holder);
} else
holder = (ViewHolder) vi.getTag();
holder.restaurantName.setText(getCustomText(resturants.get(position)
.getName()));
holder.address.setText(getCustomText(resturants.get(position)
.getAddress()));
holder.completeAddress.setText(getCustomText(resturants.get(position)
.getMergedAddress()));
holder.cuisines.setText(Html.fromHtml(getCustomText("<b>Cuisine: </b>"
+ resturants.get(position).getCuisines())));
imageLoader.DisplayImage(resturants.get(position).getImagePath(),
holder.image);
setAvalIcons(position, holder);
getDistance(position, holder);
if (resturants.get(position).getSpecialOffer() != null
&& !resturants.get(position).getSpecialOffer()
.equals(StringConstants.EMPTY_STRING)) {
holder.overlay
.setBackgroundResource(R.drawable.specialoffers_strip);
holder.overlay.invalidate();
}
return vi;
}
private void getDistance(int position, ViewHolder holder) {
Setting setting = ((AppDelegate) ((Activity)context).getApplication())
.getSetting();
Resturant resturant = resturants.get(position);
if (setting.getDistance() == 0) {
holder.metricTxt.setText("miles");
holder.distanceTxt.setText(resturant.getLocation());
} else {
holder.metricTxt.setText("kms");
holder.distanceTxt.setText(resturant.getLocationInKm());
}
}
public String getCustomText(String text) {
if (text.length() > 30) {
text = text.substring(0, 26);
text = text + "...";
}
return text.toString();
}
public void reSet(ArrayList<Resturant> resturantsCache) {
System.out.println("reSet(Resturant[] resturants) resturant :: "
+ resturantsCache.size());
this.resturants = resturants;
notifyDataSetChanged();
}
private void setAvalIcons(int position, ViewHolder holder) {
Resturant resturant = resturants.get(position);
System.out.println("Special offer image Visibility :: "
+ resturant.getSpecialIconsVisibility(0));
System.out.println("Special offer image :: " + holder.offerImg);
holder.offerImg.setVisibility(resturant.getSpecialIconsVisibility(0));
imageLoader.DisplayImage(resturant.getOfferImage(), holder.offerImg);
holder.freqImg.setVisibility(resturant.getSpecialIconsVisibility(1));
if (resturant.getSpecialIconsVisibility(1) == View.VISIBLE) {
holder.freqImg.setImageResource(resturant
.getFrequencyImageDrawableId());
}
holder.dinnerCountImg.setVisibility(resturant
.getSpecialIconsVisibility(2));
holder.dinnerCountImg.setText(resturant.getDinersPerCard() + "D");
holder.friDashImg.setVisibility(resturant.getSpecialIconsVisibility(3));
holder.friEveDashImg.setVisibility(resturant
.getSpecialIconsVisibility(4));
holder.satDashImg.setVisibility(resturant.getSpecialIconsVisibility(5));
holder.satEveDashImg.setVisibility(resturant
.getSpecialIconsVisibility(6));
holder.sunDashImg.setVisibility(resturant.getSpecialIconsVisibility(7));
holder.sunEveDashImg.setVisibility(resturant
.getSpecialIconsVisibility(8));
holder.callImg.setVisibility(resturant.getSpecialIconsVisibility(9));
}
public void clearCache() {
imageLoader.clearCache();
}
@Override
public void clear() {
clearCache();
super.clear();
}
}
列表类:
公共抽象类SearchResultAbstractActivity扩展了Activity实现 OnItemClickListener {
protected LazyListAdapter adapter;
protected SearchResults searchResults;
protected SearchCriteria searchCriteria;
protected boolean isGuest = false;
protected ProgressDialog dialog;
protected String responseString;
protected boolean isNew = false;
protected boolean isFilter = false;
private View contentView;
protected static final String RETRIVE_RESTAURANTS = "RetriveRestaurants";
protected static final String DELETE_FAVOURITES = "DeleteFavourites";
protected static final String LOADING_MSG = "please wait\n\nloading restaurants...";
Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
if (!isFinishing()) {
Bundle b = msg.getData();
String action = b.getString(StringConstants.ACTION);
if (action.equalsIgnoreCase(RETRIVE_RESTAURANTS)) {
...
((AppDelegate) getApplication())
.setSearchResults(searchResults);
ListView list = (ListView) findViewById(R.id.search_result_list);
if (searchResults.getTotalCount() == 0) {
...
} else {
if (adapter == null) {
adapter = new LazyListAdapter(SearchResultAbstractActivity.this, R.layout.search_item,
searchResults.getResturantList());
list.setAdapter(adapter);
} else {
if (list.getCount() > 0) {
list.setSelection(0);
}
adapter.reSet(searchResults.getResturantList());
list.refreshDrawableState();
}
}
}
...
}
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search_result);
Log.i("SearchResultActivity :: onStart() ",
" ==========================I'm in start ============================");
isNew = true;
setTitle();
ListView list = (ListView) findViewById(R.id.search_result_list);
registerForContextMenu(list);
list.setOnItemClickListener(this);
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
...
}
@Override
protected void onStart() {
super.onStart();
ListView list = (ListView) findViewById(R.id.search_result_list);
boolean isSet = setSearchCriteria();
AppDelegate appDelegate = (AppDelegate) getApplication();
if (isSet && (isNew || isFilter || searchCriteria.isNew())) {
if (adapter != null) {
ImageView nextBtn = (ImageView) findViewById(R.id.search_result_nextBtn);
ImageView prevBtn = (ImageView) findViewById(R.id.search_result_prevBtn);
TextView countTxt = (TextView) findViewById(R.id.search_result_countTxt);
nextBtn.setVisibility(View.GONE);
prevBtn.setVisibility(View.GONE);
countTxt.setVisibility(View.GONE);
adapter.clear();
list.getEmptyView();
searchResults.setPageNo(1);
System.out
.println("%%%%%%%%%%%%%%%%%%% Ohhhhhhh %%%%%%%%%%%%%%%%%%%%%%%");
}
getFilteredResturants();
isFilter = false;
isNew = false;
searchCriteria.setNew(false);
}
if (list.getOnItemClickListener() == null) {
Log.e("%%%%%%%%%%%%%%%%%%% Started %%%%%%%%%%%%%%%%%%%%%%% ",
"" + list.getOnItemClickListener());
list.setOnItemClickListener(this);
}
}
@Override
protected void onDestroy() {
System.out.println("Hi I'm signing offfffff..........");
if (adapter != null) {
adapter.clear();
}
super.onDestroy();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Intent previewIntend = new Intent(getApplicationContext(),
PreviewResturant.class);
...
return true;
}
protected void setNextPrevVisibility() {
ImageView nextBtn = (ImageView) findViewById(R.id.search_result_nextBtn);
if (searchResults.isNext()) {
nextBtn.setVisibility(View.VISIBLE);
} else {
nextBtn.setVisibility(View.INVISIBLE);
}
ImageView prevBtn = (ImageView) findViewById(R.id.search_result_prevBtn);
if (searchResults.isPrev()) {
prevBtn.setVisibility(View.VISIBLE);
} else {
prevBtn.setVisibility(View.INVISIBLE);
}
}
public void onPrevBtnClick(View v) {
resetLastRestId();
searchCriteria.setPrev(true);
getFilteredResturants();
searchResults.onPrev();
}
public void onNextBtnClick(View v) {
resetLastRestId();
searchCriteria.setPrev(false);
getFilteredResturants();
searchResults.onNext();
}
protected void resetLastRestId() {
searchCriteria.setLastRestId(String.valueOf(searchResults.getResturant(
searchResults.getResturantsCount() - 1).getId()));
}
protected void retriveResturants() {
if (dialog == null || dialog.isShowing() == false) {
if (((AppDelegate) getApplication())
.isNetworkAvailable(SearchResultAbstractActivity.this)) {
AsyncTask<Void, Void, Void> tempTask = new AsyncTask<Void, Void, Void>() {
ProgressDialog dialog;
protected void onPreExecute() {
Log.i("SearchActivity", "onPreExecute()");
dialog = MessageBox.showProgressDialog(
SearchResultAbstractActivity.this, dialog,
LOADING_MSG);
dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
cancel(true);
}
});
}
@Override
protected Void doInBackground(Void... params) {
try {
setSearchResult();
} catch (SocketException e) {
...
cancel(true);
} catch (SocketTimeoutException e) {
...
cancel(true);
} catch (Exception e) {
...
cancel(true);
}
return null;
}
@Override
protected void onCancelled() {
super.onCancelled();
if (dialog != null && dialog.isShowing()) {
dialog.cancel();
}
Log.i("SearchResultAbstractActivity", "onCancelled()");
}
protected void onPostExecute(Void result) {
Message message = new Message();
Bundle b = new Bundle();
b.putString(StringConstants.ACTION, RETRIVE_RESTAURANTS);
message.setData(b);
searchResults = JSONParser.parseResturants(
responseString, searchResults);
mHandler.sendMessage(message);
if (dialog != null && dialog.isShowing()) {
dialog.dismiss();
}
}
};
tempTask.execute();
} else {
MessageBox.showAlert(SearchResultAbstractActivity.this,
StringConstants.CONNECTION_ERROR_TITLE,
StringConstants.CONNECTION_ERROR_MESSAGE);
}
} else {
Log.e("dialog.isShowing() : dialog.isShowing() ",
"dialog.isShowing() " + dialog.isShowing());
}
}
protected void setSearchResult() throws SoapFault, SocketException,
Exception {
responseString = getApiCallResponse();
}
protected String getApiCallResponse() throws SoapFault, SocketException,
Exception {
// try {
return new SyncApiSoapCall(getApplicationContext(),
StringConstants.URL_RESTAURANTS,
StringConstants.METHOD_SEARCH_RESTAURANTS).callSearchApi(this,
searchCriteria);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
...
}
@Override
public boolean onContextItemSelected(MenuItem item) {
...
}
@Override
public void onContextMenuClosed(Menu menu) {
...
super.onContextMenuClosed(menu);
}
private boolean getFilteredResturants() {
MyLocationListener locationListener = ((AppDelegate) getApplication())
.getLocationListener();
Setting setting = ((AppDelegate) getApplication()).getSetting();
boolean isValid = false;
try {
if ((setting.getGps() == 1 || searchCriteria.isNearMe())
&& searchCriteria.getIsLwp() == 0
&& searchCriteria.isFavourites() == false
&& (locationListener.getLatitude().equals(
StringConstants.DEFAULT_LAT_LONG) || locationListener
.getLongitude().equals(
StringConstants.DEFAULT_LAT_LONG))) {
AlertDialog.Builder builder = new AlertDialog.Builder(
SearchResultAbstractActivity.this);
builder.setMessage(StringConstants.MSG_LOCATION_ERROR)
.setTitle(StringConstants.MSG_TITLE_LOCATION_ERROR)
.setCancelable(false)
.setPositiveButton(StringConstants.MSG_OK_TEXT,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int id) {
retriveResturants();
}
});
AlertDialog alert = builder.create();
alert.show();
} else {
isValid = true;
retriveResturants();
}
} catch (Exception e) {
// finish();
}
return isValid;
}
public void logout() {
...
}
@Override
public void onLowMemory() {
Log.e("abstract search page :: Low Memory", " May kill me !!!!");
super.onLowMemory();
}
protected abstract boolean setSearchCriteria();
protected abstract void setTitle();
protected abstract int getNoResultTitle();
// protected abstract String getNoResultMsg();
}
提前致谢。
答案 0 :(得分:0)
得到解决方案:我认为即使我触发notifyDataSetChanged(),我的列表也不会刷新;在LazyListAdapter(自定义适配器)的public void reSet(ArrayList resturantsCache)中,但实际上问题在于自定义适配器的实现。
我再次附加我的适配器代码,以便其他人可以获得解决方案。
适配器:
package com.topnosh.campus.util;
import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.topnosh.campus.AppDelegate;
import com.topnosh.campus.R;
import com.topnosh.campus.constants.StringConstants;
import com.topnosh.campus.model.Resturant;
import com.topnosh.campus.model.Setting;
public class LazyListAdapter extends ArrayAdapter<Resturant> {
public ImageLoader imageLoader;
Context context;
int layoutResourceId;
public LazyListAdapter(Context context, int layoutResourceId,
ArrayList<Resturant> resturants) {
super(context, layoutResourceId, resturants);
this.layoutResourceId = layoutResourceId;
this.context = context;
imageLoader = new ImageLoader(context);
setNotifyOnChange(true);
}
...
public void reSet(ArrayList<Resturant> resturantsCache) {
clear();
for (Resturant resturant : resturantsCache) {
add(resturant);
}
}
...
}
感谢所有注意到这个问题并试图提供帮助的人。