问题
I've been getting following out of memory issue due to layout inflater when i use my app for little longer than 7-8 minutes. I have checked through many questions in stackoverflow but have not been able to find a good solution. I tried 'android:largeHeap="true"' too, but it seems to create more problem than solve this.
The Fragment that contains the listview where i have loaded large chunk of item details which is usually causing outOfMemory error is as follows:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
viewX = inflater.inflate(R.layout.item_list, container, false);
baseURL = getResources().getString(R.string.baseURL);
((MainActivity) getActivity()).setBack(0);
((MainActivity) getActivity()).setBack_match(2);
((MainActivity) getActivity()).setBackIcon(0);
search = (SearchView) viewX.findViewById(R.id.search);
listView = (SwipeMenuListView) viewX.findViewById(R.id.listView);
layout = (LinearLayout) viewX.findViewById(R.id.layout2);
progress = (ProgressBar) viewX.findViewById(R.id.progress2);
list_notice = (TextView) viewX.findViewById(R.id.list_notice);
list_title = (TextView) viewX.findViewById(R.id.list_title);
me_latLng = ((MainActivity) getActivity()).getUserLatLng();
likeFav = ((MainActivity) getActivity()).likeFavX();
device_id = ((MainActivity) getActivity()).getDeviceId();
token = ((MainActivity) getActivity()).getToken();
BG = ((MainActivity) getActivity()).getCarBG();
if (me_latLng == null) {
me_latLng = new LatLng(0, 0);
distance_check = 1;
}
if (likeFav == 1) {
list_title.setText("LIKED CARS");
likeFav = 1;
list("like");
}
if (likeFav == 0) {
list_title.setText("FAVOURITE CARS");
likeFav = 0;
list("fav");
}
SwipeMenuCreator creator = new SwipeMenuCreator() {
@Override
public void create(SwipeMenu menu) {
// create "delete" item
SwipeMenuItem deleteItem = new SwipeMenuItem(
getActivity());
// set item background
deleteItem.setBackground(new ColorDrawable(Color.rgb(0x7a,
0x01, 0x3a)));
// set item width
deleteItem.setWidth(150);
// set a icon
deleteItem.setIcon(R.drawable.delete);
// add to menu
menu.addMenuItem(deleteItem);
}
};
listView.setMenuCreator(creator);
listView.setOnMenuItemClickListener(new SwipeMenuListView.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(int position, SwipeMenu menu, int index) {
int[] vNew = ((MainActivity) getActivity()).getPos();
final int positionNew = vNew[position];
switch (index) {
case 0:
final int position2 = position;
new AlertDialog.Builder(getActivity())
.setTitle("")
.setMessage("Are you sure you want to delete car: " + brand_list[positionNew] + ", " + model_list[positionNew])
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (likeFav == 1) {
deleteLikeFav(baseURL + "RemoveLike", "" + assetId_list[positionNew]);
} else {
deleteLikeFav(baseURL + "RemoveFavourite", "" + assetId_list[positionNew]);
}
dialog.dismiss();
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.show();
break;
}
return false;
}
});
listView.setSwipeDirection(SwipeMenuListView.DIRECTION_LEFT);
search.setOnQueryTextListener(item_list.this);
return viewX;
}
private void deleteLikeFav(final String s, final String assetIdXXX) {
RequestQueue rq = Volley.newRequestQueue(getActivity());
StringRequest postReq = new StringRequest(Request.Method.POST, s, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try {
JSONObject jsonResponse = new JSONObject(response);
String ResponseType = jsonResponse.getString("ResponseType"),
network = jsonResponse.getString("ResponseMessage");
if (network.equals("success")) {
if (likeFav == 1) {
likeFav = 1;
list("like");
} else if (likeFav == 0) {
likeFav = 0;
list("fav");
}
} else if (network.equals("Token Unavailabele or Expired!")) {
((MainActivity) getActivity()).renewToken();
token = ((MainActivity) getActivity()).getToken();
deleteLikeFav(s, assetIdXXX);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
System.out.println("Error [" + error + "]");
}
}) {
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("deviceid", device_id);
params.put("token", token);
params.put("web-method", "api");
params.put("AssetID", assetIdXXX);
return params;
}
};
rq.add(postReq);
}
public void list(String favLike) {
if (favLike.equals("fav")) {
getLikeFav(baseURL + "GetFavouriteCar");
} else {
getLikeFav(baseURL + "GetLikedCar");
}
}
AdapterView.OnItemClickListener listener = new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
int[] v = ((MainActivity) getActivity()).getPos();
int x = v[position];
((MainActivity) getActivity()).setNum_list(x);
((MainActivity) getActivity()).setList_flag("on");
((MainActivity) getActivity()).setBack(1);
Fragment fragment = new item_details();
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.linear_view, fragment).addToBackStack(null).commit();
}
};
public void getLikeFav(final String url) {
num_list = 0;
layout.setVisibility(View.VISIBLE);
RequestQueue rq = Volley.newRequestQueue(getActivity());
StringRequest postReq = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try {
String text = "Liked Car";
if (likeFav == 1) {
text = "Liked Car";
} else {
text = "Favourite Car";
}
String network = new JSONObject(response).getString("ResponseMessage");
if (network.equals("Token Unavailabele or Expired!")) {
((MainActivity) getActivity()).renewToken();
token = ((MainActivity) getActivity()).getToken();
getLikeFav(url);
}
JSONArray array = new JSONObject(response).getJSONArray(text);
arrayLength_list = array.length();
assetId_list = new int[array.length()];
brand_list = new String[array.length()];
model_list = new String[array.length()];
version_list = new String[array.length()];
price_list = new int[array.length()];
fuel_list = new String[array.length()];
color_list = new String[array.length()];
fav_list = new String[array.length()];
trans_list = new String[array.length()];
doors_list = new String[array.length()];
newOld_list = new String[array.length()];
image_list = new String[array.length()];
d_num_list = new String[array.length()];
d_name_list = new String[array.length()];
d_street_list = new String[array.length()];
d_zip_list = new String[array.length()];
d_location_list = new String[array.length()];
d_phone_list = new String[array.length()];
d_email_list = new String[array.length()];
d_image_list = new String[array.length()];
d_lat_list = new String[array.length()];
d_long_list = new String[array.length()];
d_whatsApp_list = new String[array.length()];
distance_list = new String[array.length()];
((MainActivity) getActivity()).setposPos(array.length());
((MainActivity) getActivity()).setDistance_array(array.length());
for (int i = 0; i < array.length(); i++) {
JSONObject j_object = array.getJSONObject(i);
assetId_list[i] = j_object.getInt("AssetID");
brand_list[i] = j_object.getString("Brand");
model_list[i] = j_object.getString("Model");
version_list[i] = j_object.getString("Version");
price_list[i] = j_object.getInt("Price");
fuel_list[i] = j_object.getString("Fuel");
color_list[i] = j_object.getString("Color");
trans_list[i] = j_object.getString("Transmission");
doors_list[i] = j_object.getString("NumDoors");
newOld_list[i] = j_object.getString("NewVehicle");
image_list[i] = j_object.getString("ImagePath");
if (likeFav == 1) {
fav_list[i] = j_object.getString("Favourite");
} else {
fav_list[i] = "true";
}
d_num_list[i] = j_object.getString("RDCProviderNumber");
d_name_list[i] = j_object.getString("ProviderName");
d_street_list[i] = j_object.getString("ProviderStreetName");
d_zip_list[i] = j_object.getString("ProviderZipCode");
d_location_list[i] = j_object.getString("ProviderLocation");
d_phone_list[i] = j_object.getString("ProviderPhone");
d_whatsApp_list[i] = j_object.getString("WhatsAppNumber");
d_email_list[i] = j_object.getString("ProviderEmail");
d_image_list[i] = j_object.getString("ProviderImage");
d_lat_list[i] = j_object.getString("Latitude");
d_long_list[i] = j_object.getString("Longitude");
}
data = new ArrayList<Data>();
for (int i = 0; i < brand_list.length; i++) {
String priceStandard = "";
String price2X = "" + price_list[i];
if (price2X.length() > 6) {
String priceX1 = new StringBuffer(price2X).insert(price2X.length() - 6, ".").toString();
priceStandard = new StringBuffer(priceX1).insert(priceX1.length() - 3, ".").toString();
} else {
priceStandard = new StringBuffer(price2X).insert(price2X.length() - 3, ".").toString();
}
if (d_lat_list[i].equals("")) {
d_lat_list[i] = "0.0";
}
if (d_long_list[i].equals("")) {
d_long_list[i] = "0.0";
}
distance_list[i] = getDistance(me_latLng, new LatLng(Double.parseDouble(d_lat_list[i]), Double.parseDouble(d_long_list[i])));
Data searchList = new Data(model_list[i], brand_list[i], version_list[i], image_list[i], priceStandard + ",-", newOld_list[i], fav_list[i], distance_list[i], i);
data.add(searchList);
((MainActivity) getActivity()).setPos(i, i);
}
myAdapter = new MyAdapter(getActivity(), data);
listView.setAdapter(myAdapter);
listView.setTextFilterEnabled(true);
listView.setOnItemClickListener(listener);
((MainActivity) getActivity()).setList(assetId_list, image_list, brand_list, model_list, version_list, price_list, newOld_list, color_list, fuel_list, doors_list, fav_list, trans_list,
d_name_list, d_location_list, d_street_list, d_phone_list, d_image_list, d_lat_list, d_long_list, d_whatsApp_list, d_num_list, d_email_list);
if (array.length() == 0) {
layout.setVisibility(View.VISIBLE);
progress.setVisibility(View.GONE);
list_notice.setVisibility(View.VISIBLE);
if (likeFav == 1) {
list_notice.setText("No liked cars to display");
} else {
list_notice.setText("No favourite cars to display");
}
} else {
layout.setVisibility(View.GONE);
progress.setVisibility(View.VISIBLE);
list_notice.setVisibility(View.GONE);
}
} catch (Exception e) {
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
System.out.println("Error [" + error + "]");
}
}) {
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("deviceid", device_id);
params.put("token", token);
params.put("web-method", "api");
return params;
}
};
rq.add(postReq);
}
public String getDistance(LatLng my_latlong, LatLng frnd_latlong) {
String dist;
if (distance_check == 0) {
Location l1 = new Location("One");
l1.setLatitude(my_latlong.latitude);
l1.setLongitude(my_latlong.longitude);
Location l2 = new Location("Two");
l2.setLatitude(frnd_latlong.latitude);
l2.setLongitude(frnd_latlong.longitude);
float distance = l1.distanceTo(l2);
int dd = (int) (distance / 1000);
dist = dd + "";
if (dist.equals("0")) {
dist = "<1";
}
} else {
dist = " ";
}
return dist;
}
@Override
public boolean onQueryTextSubmit(String query) {
if (searchCheck == 1) {
myAdapter.getFilter().filter(query);
}
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
if (searchCheck == 1) {
myAdapter.getFilter().filter(newText);
}
return false;
}
public class MyAdapter extends BaseAdapter implements Filterable {
ArrayList<Data> dataList = null;
ArrayList<Data> mStringFilterList;
ValueFilter valueFilter;
View row = null;
private Context context;
public MyAdapter(Context context, ArrayList<Data> data) {
this.context = context;
this.dataList = data;
this.mStringFilterList = new ArrayList<Data>();
this.mStringFilterList = data;
}
public class ViewHolderV {
ImageView carImageV;
TextView brandV;
TextView modelV;
TextView priceV;
TextView newOldV;
ImageView bgV;
ImageView favV;
TextView distanceV;
TextView positionV;
}
@Override
public int getCount() {
return dataList.size();
}
@Override
public Object getItem(int position) {
return dataList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolderV viewHolder = new ViewHolderV();
dataV = dataList.get(position);
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.list_view, parent, false);
((MainActivity) getActivity()).setNum_list(position);
viewHolder.brandV = (TextView) row.findViewById(R.id.list_brand);
viewHolder.modelV = (TextView) row.findViewById(R.id.list_here);
viewHolder.priceV = (TextView) row.findViewById(R.id.list_price);
viewHolder.newOldV = (TextView) row.findViewById(R.id.list_oldNew);
viewHolder.distanceV = (TextView) row.findViewById(R.id.list_distance);
viewHolder.carImageV = (ImageView) row.findViewById(R.id.list_car);
viewHolder.bgV = (ImageView) row.findViewById(R.id.list_bg);
viewHolder.favV = (ImageView) row.findViewById(R.id.list_fav);
viewHolder.positionV = (TextView) row.findViewById(R.id.list_position);
row.setTag(viewHolder);
} else {
viewHolder = (ViewHolderV) convertView.getTag();
}
((MainActivity) getActivity()).setDistance_list(dataV.getDistance_data());
((MainActivity) getActivity()).setPos(position, dataV.getPosition_data());
viewHolder.brandV.setText(dataV.getBrand_data() + " " + dataV.getModel_data());
viewHolder.modelV.setText(dataV.getVersion_data());
viewHolder.priceV.setText("" + dataV.getPrice_data());
viewHolder.newOldV.setText(dataV.getNewOld_data());
viewHolder.positionV.setText("" + dataV.getPosition_data());
Picasso.with(getActivity()).load(dataV.getImage_data()).into(viewHolder.carImageV);
Picasso.with(getActivity()).load(BG).into(viewHolder.bgV);
viewHolder.distanceV.setText(dataV.getDistance_data() + " KM");
if (dataV.getFav_data().equals("true")) {
viewHolder.favV.setImageResource(R.drawable.fav);
} else {
viewHolder.favV.setImageResource(R.drawable.fav2);
}
searchCheck = 1;
return row;
}
@Override
public Filter getFilter() {
if (valueFilter == null) {
valueFilter = new ValueFilter();
}
return valueFilter;
}
private class ValueFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
((MainActivity) getActivity()).setPosNil();
if (constraint.length() == 0) {
results.count = mStringFilterList.size();
results.values = mStringFilterList;
// mStringFilterList.addAll(dataList);
((MainActivity) getActivity()).setposPos(mStringFilterList.size());
} else {
ArrayList<Data> filterList = new ArrayList<Data>();
for (int i = 0; i < mStringFilterList.size(); i++) {
if ((mStringFilterList.get(i).getBrand_data().toUpperCase() + " " + mStringFilterList.get(i).getModel_data().toUpperCase())
.contains(constraint.toString().toUpperCase()) || (mStringFilterList.get(i).getVersion_data().toUpperCase())
.contains(constraint.toString().toUpperCase())) {
Data d = new Data(mStringFilterList.get(i)
.getModel_data(), mStringFilterList.get(i)
.getBrand_data(), mStringFilterList.get(i)
.getVersion_data(), mStringFilterList.get(i)
.getImage_data(), mStringFilterList.get(i)
.getPrice_data(), mStringFilterList.get(i)
.getNewOld_data(), mStringFilterList.get(i)
.getFav_data(), mStringFilterList.get(i)
.getDistance_data(), mStringFilterList.get(i)
.getPosition_data());
filterList.add(d);
}
}
results.count = filterList.size();
results.values = filterList;
((MainActivity) getActivity()).setposPos(filterList.size());
}
return results;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
dataList = (ArrayList<Data>) results.values;
notifyDataSetChanged();
}
}
}
回答1:
the problem is with your view holder. ViewHolder pattern is used to optimise the memory taken by the list. it will create View objects only for the visible part, but in your case every time you are creating a ViewHolder, so whenever you scroll the number of objects will increase and it will cause OutOfMemoryException, the only way to correct is, you need to have some changes in you code. please refer this url. also see the example
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolderItem viewHolder;
// The convertView argument is essentially a "ScrapView" as described is Lucas post
// http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/
// It will have a non-null value when ListView is asking you recycle the row layout.
// So, when convertView is not null, you should simply update its contents instead of inflating a new row layout.
if(convertView==null){
// inflate the layout
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
convertView = inflater.inflate(layoutResourceId, parent, false);
// well set up the ViewHolder
viewHolder = new ViewHolderItem();
viewHolder.textViewItem = (TextView) convertView.findViewById(R.id.textViewItem);
// store the holder with the view.
convertView.setTag(viewHolder);
}else{
// we've just avoided calling findViewById() on resource everytime
// just use the viewHolder
viewHolder = (ViewHolderItem) convertView.getTag();
}
....................
.............
}
来源:https://stackoverflow.com/questions/35447883/out-of-memory-error-after-using-app-for-more-than-5-10-mins