我手头有一个奇怪的 ListView 显示问题。我的应用程序显示状态图标和商店地址列表。列表的每一行都包含一个图像视图和一个文本视图。可以通过选择不同的日期来更改 ListView 显示。日期由 ListView 上方的单选按钮组选择。他们是昨天、今天和明天。
ListView 显示在针对皮肤 WQVGA400 的 Google API 级别 17 的模拟器中运行良好。但是,它在 Galaxy S3 手机上仅显示昨天和今天的空白行。该行的图标和文本在那里,我可以通过单击一行来验证并在弹出窗口中查看内容。ListView 在 Galaxy S3 上一直适用于明天的数据。我的应用程序清单文件指定了 android:minSdkVersion="14" 和 android:targetSdkVersion="17"。我的 ListView 充满了自定义适配器。
我在互联网上做了很多研究,但找不到答案。我怀疑这与内存问题有关。谁能帮助回答如何解决这个缺陷?提前致谢。
这是一些相关的代码。希望他们提供足够的信息。
包含 ListView 的片段 XML:
<RadioGroup android:id="@+id/radioVisitDate" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> ... </RadioGroup> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:background="#1BD6E0"> <TextView android:id="@+id/visit_status_header" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:foreground="#000000" android:text="@string/visit_status" /> ... </LinearLayout> <ListView android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="fill_parent" android:background="#FFFFFF" android:drawSelectorOnTop="false"/>
片段的代码文件:
...
public class PugsMobileStoreStopsFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor>
{
public interface OnFragmentEventsListener
{
public void onCursorLoadStatus(Intent loadStatusIntent);
public void onGetStoreStopsServiceStart(Intent startGetStoreStopsServiceIntent);
public void OnUserSettingsErrorListener(Intent correctUserSettingsIntent);
}
private OnFragmentEventsListener fragmentEventListener;
private Intent loadStatusIntent = null;
private Intent getStoreStopsServiceStatusIntent = null;
private Intent getOrderLineItemsIntent = null;
private Intent correctUserSettingsIntent = null;
private Handler handler = new Handler();
private SparseArray<PugsMobileStoreStopInfo> storeStopInfos = null;
private PugsMobileStoreStopsAdapter storeStopInfosAdapter;
private ListView storeStopsListView = null;
private Calendar visitDate = Calendar.getInstance();
private boolean tomorrowSeleted = false;
private SharedPreferences prefs = null;
private SharedPreferences.Editor prefsEditor;
private int salesRepNumber = 0;
private boolean salesRepNumEmptyAlertDisplayed = false;
private boolean salesRepNumNonNumericAlertDisplayed = false;
private SharedPreferences sharedPref = null;
private SharedPreferences.Editor editor = null;
private int selectedBtnId = 0;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.pugs_mobile_store_stops_fragment, null);
storeStopsListView = (ListView) view.findViewById(android.R.id.list);
storeStopsListView.setItemsCanFocus(false);
setHasOptionsMenu(true);
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
storeStopInfos = new SparseArray<PugsMobileStoreStopInfo>();
getLoaderManager().initLoader(PugsMobileConstansDefinition.DataRequester.ENUM_STORE_VISIT.ordinal(), null, this);
RadioGroup daySelectionRadiogroup = (RadioGroup)getActivity().findViewById(R.id.radioVisitDate);
restoreVisitDateSelection();
daySelectionRadiogroup.setOnCheckedChangeListener(new OnCheckedChangeListener(){
public void onCheckedChanged(RadioGroup group, int radioButtonId) {
// checkedId is the RadioButton selected
switch(radioButtonId)
{
case R.id.radioYesterday:
tomorrowSeleted = false;
visitDate = PugsMobileUtilities.getYesterday();
resetStoreStopListView();
break;
case R.id.radioToday:
tomorrowSeleted = false;
visitDate = Calendar.getInstance();
resetStoreStopListView();
break;
case R.id.radioTomorrow:
tomorrowSeleted = true;
visitDate= PugsMobileUtilities.getTomorrow();
resetStoreStopListView();
break;
default:
break;
}
}
});
Thread t =
new Thread(new Runnable(){
public void run()
{
updateStoreStops();
}
});
t.start();
}
private void restoreVisitDateSelection()
{
if (selectedBtnId > 0)
{
((RadioButton) getActivity().findViewById(selectedBtnId)).setSelected(true);
}
}
private void resetStoreStopListView()
{
handler.post(new Runnable(){
public void run()
{
storeStopsListView.setAdapter(null);
getLoaderManager().restartLoader(PugsMobileConstansDefinition.DataRequester.ENUM_STORE_VISIT.ordinal(), null, PugsMobileStoreStopsFragment.this);
}
});
}
public void saveFragmentVariaqbles()
{
sharedPref = getActivity().getSharedPreferences(PugsMobileConstansDefinition.PUGS_MOBILE_SHARED_PREF, getActivity().MODE_PRIVATE);
if (null != sharedPref)
{
RadioGroup g = (RadioGroup) getActivity().findViewById(R.id.radioVisitDate);
selectedBtnId = g.getCheckedRadioButtonId();
editor = sharedPref.edit();
editor.putInt(PugsMobileConstansDefinition.SELECTED_VISIT_DATE_RADIO_BUTTON, selectedBtnId);
editor.commit();
}
}
...
public void updateStoreStops()
{
boolean bRemovePreviousSalesRepData = false;
Integer salesRepNumber = getSalesRepNumber();
int prevSalesRepNumber = getPreviousSalesRepNumber();
if (salesRepNumber == PugsMobileConstansDefinition.EMPTY_TEXT_ERR_CODE || salesRepNumber == PugsMobileConstansDefinition.NON_NUMERIC_TEXT_ERR_CODE )
{
return;
}
if (prevSalesRepNumber == salesRepNumber.intValue())
{
handler.post(new Runnable() {
public void run() {
getLoaderManager().restartLoader(PugsMobileConstansDefinition.DataRequester.ENUM_STORE_VISIT.ordinal(), null, PugsMobileStoreStopsFragment.this);
}
});
}
else
{
prefsEditor = prefs.edit();
prefsEditor.putString(UserSettingsActivity.SETTINGS_PREVIOUS_ROUTE_NUMBER,salesRepNumber.toString());
prefsEditor.commit();
if (prevSalesRepNumber > 0)
{
bRemovePreviousSalesRepData = true;
}
startDataService(PugsMobileConstansDefinition.DataRequester.ENUM_STORE_VISIT.ordinal(), bRemovePreviousSalesRepData);
}
}
public void updateStoreVisitListView()
{
requestStoreStopsInfo();
}
@Override
public void onAttach(Activity activity)
{
super.onAttach(activity);
try
{
fragmentEventListener = (OnFragmentEventsListener) activity;
}
catch (ClassCastException e)
{
throw new ClassCastException(activity.toString() + " must implement OnFragmentEventsListener");
}
}
public Loader<Cursor> onCreateLoader(int id, Bundle args)
{
CursorLoader loader = null;
if (IsSalesRepNumberValid())
{
...
}
return loader;
}
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor)
{
retrieveDataFromCursor(cursor,loader.getId());
}
public void onLoaderReset(Loader<Cursor> loader)
{
switch(PugsMobileConstansDefinition.dataRequesterEnums[loader.getId()])
{
case ENUM_STORE_VISIT: storeStopsListView.setAdapter(null);
break;
default:
break;
}
}
private CursorLoader getStoreStopsLoader()
{
...
return loader;
}
private CursorLoader getRefreshStoreStopsLoader()
{
...
return loader;
}
private void processStoreStopsData(Cursor cursor)
{
int count = 0;
try
{
if (null != cursor)
{
String storeAddress = null;
int visitStatus = 0;
int rowIndex = -1;
PugsMobileStoreStopInfo storeStopInfo = null;
count = cursor.getCount();
if (0 == count)
{
return;
}
if (null != storeStopInfos)
{
storeStopInfos.clear();
storeStopInfos = null;
}
storeStopInfos = new SparseArray<PugsMobileStoreStopInfo>();
PugsMobileAlarmReceiver.geoDataList.clear();
while(cursor.moveToNext())
{
rowIndex = cursor.getPosition();
storeStopInfo = new PugsMobileStoreStopInfo();
storeStopInfo.setStoreName(cursor.getString(cursor.getColumnIndexOrThrow(PugsMobileStoreVisitInfoTable.COLUMN_STORE_NAME)));
storeAddress += " ";
storeAddress = cursor.getString(cursor.getColumnIndexOrThrow(PugsMobileStoreVisitInfoTable.COLUMN_STREET_ADDRESS));
storeAddress += ", " + cursor.getString(cursor.getColumnIndexOrThrow(PugsMobileStoreVisitInfoTable.COLUMN_STORE_CITY));
storeAddress += ", " + cursor.getString(cursor.getColumnIndexOrThrow(PugsMobileStoreVisitInfoTable.COLUMN_STORE_STATE));
storeStopInfo.setStoreAddress(storeAddress);
visitStatus = cursor.getInt(cursor.getColumnIndexOrThrow(PugsMobileStoreVisitInfoTable.COLUMN_VISIT_STATUS));
if (tomorrowSeleted)
{
visitStatus = 3;
}
storeStopInfo.setStoreVisitStatus(visitStatus);
storeStopInfo.setStoreId(cursor.getInt(cursor.getColumnIndexOrThrow(PugsMobileStoreVisitInfoTable.COLUMN_STORE_ID)));
storeStopInfo.setListHeaderId(cursor.getInt(cursor.getColumnIndexOrThrow(PugsMobileStoreVisitInfoTable.COLUMN_LISTHEADER_ID)));
storeStopInfo.setBillId(cursor.getInt(cursor.getColumnIndexOrThrow(PugsMobileStoreVisitInfoTable.COLUMN_STORE_BILL_ID)));
PugsGeoDataInfo storeGeoInfo = new PugsGeoDataInfo();
storeGeoInfo.setLatitude(Double.parseDouble(cursor.getString(cursor.getColumnIndexOrThrow(PugsMobileStoreVisitInfoTable.COLUMN_STORE_LATITUDE))));
storeGeoInfo.setLongitude(Double.parseDouble(cursor.getString(cursor.getColumnIndexOrThrow(PugsMobileStoreVisitInfoTable.COLUMN_STORE_LONGITUDE))));
PugsMobileAlarmReceiver.geoDataList.add(storeGeoInfo);//Save store geo data
storeStopInfos.append(rowIndex, storeStopInfo);
}
if (null != storeStopInfos.get(0))
{
handler.post(new Runnable(){public void run() {populateStoreStopsList(storeStopInfos);}});
}
else
{
updateStoreStops();
}
}
}
catch(Exception e)
{
e.fillInStackTrace();
}
}
private synchronized void retrieveDataFromCursor(Cursor cursor, int dataRequesterID)
{
loadStatusIntent = null;
loadStatusIntent = new Intent();
loadStatusIntent.setAction(PugsMobileConstansDefinition.LOAD_FINISHED);
fragmentEventListener.onCursorLoadStatus(loadStatusIntent);
switch(PugsMobileConstansDefinition.dataRequesterEnums[dataRequesterID])
{
case ENUM_STORE_VISIT:
processStoreStopsData(cursor);
break;
case ENUM_REFRESH_STORE_VISIT:
processStoreStopsData(cursor);
break;
default:
break;
}
}
private void populateStoreStopsList(SparseArray<PugsMobileStoreStopInfo> storeStops)
{
//Initialize the adapter sending the current context
storeStopInfosAdapter = new PugsMobileStoreStopsAdapter(getActivity(), storeStops);
storeStopInfosAdapter.notifyDataSetChanged();
storeStopsListView.setAdapter(storeStopInfosAdapter);
}
private void startDataService(int dataType, boolean bRemovePreviousSalesRepData)
{
Intent dataIntent = new Intent(getActivity(), PugsMobileDataService.class);
...
getActivity().startService(dataIntent);
}
/* @param variableName - name of drawable, e.g R.drawable.<b>image</b>
* @param � - class of resource, e.g R.drawable, of R.raw
* @return integer id of resource
*/
public static int getResId(String variableName, Class<?> c)
{
Field field = null;
int resId = 0;
try
{
field = c.getField(variableName);
try
{
resId = field.getInt(null);
}
catch (Exception e)
{
e.printStackTrace();
}
}
catch (Exception e)
{
e.printStackTrace();
}
return resId;
}
public int getSalesRepNumber()
{
prefs = PreferenceManager.getDefaultSharedPreferences(getActivity().getApplicationContext());
String strSalesRepNum = prefs.getString(UserSettingsActivity.SETTINGS_ROUTE_NUMBER, "none");
strSalesRepNum.trim();
if (strSalesRepNum.equalsIgnoreCase("none"))
{
return PugsMobileConstansDefinition.EMPTY_TEXT_ERR_CODE;
}
else if (!isNumeric(strSalesRepNum))
{
//salesRepNumEmptyAlertDisplayed = false;
salesRepNumNonNumericAlertDisplayed = false;
return PugsMobileConstansDefinition.NON_NUMERIC_TEXT_ERR_CODE;
}
return Integer.parseInt(strSalesRepNum);
}
public int getPreviousSalesRepNumber()
{
prefs = PreferenceManager.getDefaultSharedPreferences(getActivity().getApplicationContext());
String strSalesRepNum = prefs.getString(UserSettingsActivity.SETTINGS_PREVIOUS_ROUTE_NUMBER, "none");
strSalesRepNum.trim();
if (strSalesRepNum.equalsIgnoreCase("none"))
{
return 0;
}
return Integer.parseInt(strSalesRepNum);
}
public boolean isNumeric(String s)
{
return s.matches("\\d+");
}
public void requestStoreStopsInfo()
{
getStoreStopsServiceStatusIntent = null;
getStoreStopsServiceStatusIntent = new Intent();
getStoreStopsServiceStatusIntent.setAction(PugsMobileConstansDefinition.PUGS_MOBILE_MESSAGE_SENT_ACTION);
getStoreStopsServiceStatusIntent.putExtra(PugsMobileConstansDefinition.PUGS_MOBILE_MESSAGE_EXTRA, PugsMobileConstansDefinition.STORE_STOPS_SERVICE_STARTED);
fragmentEventListener.onGetStoreStopsServiceStart(getStoreStopsServiceStatusIntent);
//If SQLite db is empty, then get data from SQL server
Thread t = new Thread(new Runnable() {
public void run() {
startDataService(PugsMobileConstansDefinition.DataRequester.ENUM_STORE_VISIT.ordinal(), false);
}
});
t.start();
}
public void requestLineItemsInfo()
{
getOrderLineItemsIntent = null;
getOrderLineItemsIntent = new Intent();
getOrderLineItemsIntent.setAction(PugsMobileConstansDefinition.PUGS_MOBILE_MESSAGE_SENT_ACTION);
getOrderLineItemsIntent.putExtra(PugsMobileConstansDefinition.PUGS_MOBILE_MESSAGE_EXTRA, PugsMobileConstansDefinition.ORDER_LINE_ITEMS_SERVICE_STARTED);
fragmentEventListener.onGetStoreStopsServiceStart(getOrderLineItemsIntent);
//If SQLite db is empty, then get data from SQL server
Thread t = new Thread(new Runnable() {
public void run() {
startDataService(PugsMobileConstansDefinition.DataRequester.ENUM_ORDER_LINE_ITEMS.ordinal(), false);
}
});
t.start();
}
private boolean IsSalesRepNumberValid()
{
boolean bValid = true;
salesRepNumber = getSalesRepNumber();
correctUserSettingsIntent = null;
correctUserSettingsIntent = new Intent();
correctUserSettingsIntent.putExtra(PugsMobileConstansDefinition.SALESREP_NUMBER_EMPTY, false);
correctUserSettingsIntent.putExtra(PugsMobileConstansDefinition.SALESREP_NUMERIC_ID_NEEDED, false);
if (PugsMobileConstansDefinition.EMPTY_TEXT_ERR_CODE == salesRepNumber)
{
if (!salesRepNumEmptyAlertDisplayed)
{
correctUserSettingsIntent.putExtra(PugsMobileConstansDefinition.SALESREP_NUMBER_EMPTY, true);
fragmentEventListener.OnUserSettingsErrorListener(correctUserSettingsIntent);
salesRepNumEmptyAlertDisplayed = true;
}
bValid = false;
}
else if (PugsMobileConstansDefinition.NON_NUMERIC_TEXT_ERR_CODE == salesRepNumber)
{
if (!salesRepNumNonNumericAlertDisplayed)
{
correctUserSettingsIntent.putExtra(PugsMobileConstansDefinition.SALESREP_NUMERIC_ID_NEEDED, true);
fragmentEventListener.OnUserSettingsErrorListener(correctUserSettingsIntent);
salesRepNumNonNumericAlertDisplayed = true;
}
bValid = false;
}
return bValid;
}
}
- 填充列表视图的自定义适配器代码
……
public class PugsMobileStoreStopsAdapter extends BaseAdapter implements OnClickListener
{
private SparseArray<PugsMobileStoreStopInfo> storeStops = null;
private LayoutInflater mInflater;
private ViewHolder holder = null;
private Context context = null;
public PugsMobileStoreStopsAdapter(Context context, SparseArray<PugsMobileStoreStopInfo> storeStopInfos)
{
if (null != storeStops)
{
storeStops.clear();
storeStops = null;
}
this.storeStops = storeStopInfos;
this.context = context;
mInflater = LayoutInflater.from(context);
}
public int getCount()
{
return storeStops.size();
}
public PugsMobileStoreStopInfo getItem(int position)
{
return storeStops.get(position);
}
public long getItemId(int position)
{
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
if (convertView == null)
{
holder = null;
holder = new ViewHolder();
mInflater=(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(R.layout.pugsmobile_store_stop_row_layout, parent,false);
holder.storeVisitStatus = (ImageView) convertView.findViewById(R.id.storeVisitStatus);
holder.storeNameAddress = (TextView) convertView.findViewById(R.id.storeNameAddress);
holder.storeId = (TextView) convertView.findViewById(R.id.storeId);
holder.listHeaderId = (TextView) convertView.findViewById(R.id.listHeaderId);
holder.billId = (TextView) convertView.findViewById(R.id.billId);
convertView.setTag(holder);
convertView.setOnClickListener(new onItemClickListener(position));
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.storeNameAddress.setText(storeStops.get(position).getStoreName() + ", " + storeStops.get(position).getStoreAddress());
holder.storeId.setText(storeStops.get(position).getStoreId().toString());
holder.listHeaderId.setText(storeStops.get(position).getListHeaderId().toString());
holder.billId.setText(storeStops.get(position).getBillId().toString());
switch(storeStops.get(position).getStoreVisitStatus())
{
case 0:
holder.storeVisitStatus.setImageResource(R.drawable.redicon);
break;
case 1:
holder.storeVisitStatus.setImageResource(R.drawable.yellowicon);
break;
case 2:
holder.storeVisitStatus.setImageResource(R.drawable.greenicon);
break;
case 3:
holder.storeVisitStatus.setImageResource(R.drawable.greyicon);
break;
default:
break;
}
return convertView;
}
@Override
public void onClick(View v)
{
Log.v("TAG", "Row button clicked");
}
public static class ViewHolder
{
ImageView storeVisitStatus;
TextView storeNameAddress;
TextView storeId;
TextView listHeaderId;
TextView billId;
}
private class onItemClickListener implements OnClickListener
{
private int mPosition;
onItemClickListener(int position)
{
mPosition = position;
}
@Override
public void onClick(View arg0)
{
ViewHolder holder =(ViewHolder)arg0.getTag();
StringTokenizer tokens = new StringTokenizer((String)holder.storeNameAddress.getText(), ",");
String storeName = tokens.nextToken();// this will contain store name alone
Intent launchOrderTypeSelectionIntent = new Intent(context, PugsMobileNewOrderActivity.class);
launchOrderTypeSelectionIntent.putExtra(PugsMobileConstansDefinition.STORE_NAME, storeName);
launchOrderTypeSelectionIntent.putExtra(PugsMobileConstansDefinition.PUGSMOBILE_STORE_ID, Integer.parseInt((String)holder.storeId.getText()));
launchOrderTypeSelectionIntent.putExtra(PugsMobileConstansDefinition.PUGSMOBILE_LIST_HEADER_ID, Integer.parseInt((String)holder.listHeaderId.getText()));
launchOrderTypeSelectionIntent.putExtra(PugsMobileConstansDefinition.PUGSMOBILE_BILL_ID, Integer.parseInt((String)holder.billId.getText()));
context.startActivity(launchOrderTypeSelectionIntent);
/*
String[] projection =
new String[] {PugsMobileStoreVisitInfoTable.COLUMN_STORE_NAME,
PugsMobileStoreVisitInfoTable.COLUMN_STORE_ID
};
String where = PugsMobileStoreVisitInfoTable.COLUMN_STORE_ID + " = " + storeIdText;
ContentResolver cr = context.getContentResolver();
Cursor result = cr.query(PugsMobileConstansDefinition.STORE_VISIT_INFO_CONTENT_URI, projection, where, null, null);
try
{
if (result.moveToFirst())
{
String storeName = result.getString(result.getColumnIndexOrThrow(PugsMobileStoreVisitInfoTable.COLUMN_STORE_NAME));
int storeId = Integer.parseInt(result.getString(result.getColumnIndexOrThrow(PugsMobileStoreVisitInfoTable.COLUMN_STORE_ID)));
Intent launchOrderTypeSelectionIntent =
new Intent(context, PugsMobileOrderTypeSelectionActivity.class);
launchOrderTypeSelectionIntent.putExtra(PugsMobileConstansDefinition.STORE_NAME, storeName);
launchOrderTypeSelectionIntent.putExtra(PugsMobileConstansDefinition.PUGSMOBILE_STORE_ID, storeId);
context.startActivity(launchOrderTypeSelectionIntent);
}
}
catch(Exception e)
{
e.fillInStackTrace();
}*/
//Log.v(TAG, "onItemClick at position" + mPosition);
}
}
}