#android #listview #android-studio
#Android #listview #android-studio
Вопрос:
Я пытаюсь создать listview с фоновым изображением для каждого элемента и текстовым представлением, которое отображается сверху. Представление списка заполняется нормально, но нажатие на элемент напрямую выдает ошибку.
Вот мой элемент просмотра списка xml (menu_section.xml )
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="75dp">
<ImageView
android:id="@ id/section_bg_image"
android:layout_width="match_parent"
android:layout_height="75dp"
android:adjustViewBounds="true"
android:scaleType="centerCrop"/>
<TextView
android:id="@ id/section_title"
android:layout_width="match_parent"
android:layout_height="75dp"
android:layout_gravity="end"
android:background="@color/colorBlackTranslucent"
android:gravity="right|center_vertical"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:text="Hello World"
android:textColor="@color/colorWhite"
android:textSize="24sp" />
</RelativeLayout>
Это мой адаптер MenuAdapter.java . Я загружаю изображения для фона из папки активов. Каждое изображение имеет ~ 50 КБ, и на данный момент в общей сложности ~ 400 КБ изображений (с 8 элементами в списке)
import android.app.Activity;
import android.content.Context;
import android.content.res.AssetManager;
import android.net.Uri;
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.squareup.picasso.Picasso;
import java.util.List;
import com.myapp.hotel.MyUtility;
import com.myapp.hotel.R;
public class MenuAdapter extends ArrayAdapter<MenuSection> {
Context context;
List<MenuSection> menuSections;
AssetManager assetManager;
String imageUrl;
public MenuAdapter(Context context, int resource, List<MenuSection> objects) {
super(context, resource, objects);
this.context = context;
this.menuSections = objects;
this.assetManager = context.getAssets();
}
@Override
public int getCount() {
return menuSections.size();
}
@Override
public MenuSection getItem(int i) {
return menuSections.get(i);
}
@Override
public long getItemId(int i) {
return menuSections.indexOf(getItemId(i));
}
/* private view holder class */
private class ViewHolder {
ImageView menuSectionImage;
TextView menuSectionItemText;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder holder = null;
LayoutInflater mInflater = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (view == null) {
view = mInflater.inflate(R.layout.menu_section, null);
holder = new ViewHolder();
holder.menuSectionItemText = (TextView) view.findViewById(R.id.section_title);
holder.menuSectionImage = (ImageView) view.findViewById(R.id.section_bg_image);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
MenuSection menuSection = menuSections.get(i);
holder.menuSectionItemText.setText(menuSection.getSectionName());
try {
imageUrl = menuSection.getImagePath();
if (!MyUtility.isNullOrEmpty(imageUrl)) {
Picasso.with(holder.menuSectionImage.getContext())
.load(Uri.parse(imageUrl))
.into(holder.menuSectionImage);
}
} catch (Exception ex) {
ex.printStackTrace();
}
return view;
}
}
и это фрагмент RestaurantFragment.java
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
import java.util.List;
import com.myapp.hotel.MyUtility;
import com.myapp.hotel.R;
/**
* A simple {@link Fragment} subclass.
*/
public class RestaurantFragment extends Fragment {
MenuAdapter adapter;
List<MenuSection> menuSections;
View view;
public RestaurantFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
if(view == null) {
view = inflater.inflate(R.layout.fragment_restaurant, container, false);
}
//adapter = new ArrayAdapter<String>(RestaurantFragment.this.getContext(), R.layout.menu_view, R.id.menu_text, MyUtility.getMenuSections().toArray(new String[MyUtility.getMenuSections().size()]));
ListView listView = (ListView) view.findViewById(R.id.menu);
menuSections = MyUtility.getMenuSections();
adapter = new MenuAdapter(RestaurantFragment.this.getContext(), R.layout.menu_section, menuSections);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Toast.makeText(RestaurantFragment.this.getActivity(), "Hello World",
Toast.LENGTH_SHORT).show();
}
});
//listView.setOnItemClickListener();
//listView.setAdapter(adapter);
/*
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Intent intent = new Intent(RestaurantFragment.this.getContext(), RestaurantMenuDetailsActivity.class);
intent.putExtra("menu_section", adapter.getItem(position).toString());
startActivity(intent);
}
});
*/
return view;
}
}
Это ошибка, которую я вижу в logcat
10-07 19:27:14.445 14925-14925/com.myapp.hotel E/InputEventReceiver: Exception dispatching input event.
10-07 19:27:14.445 14925-14925/com.myapp.hotel E/MessageQueue-JNI: Exception in MessageQueue callback: handleReceiveCallback
10-07 19:27:17.155 14925-14925/com.myapp.hotel E/art: Throwing OutOfMemoryError "Failed to allocate a 10109874 byte allocation with 8141766 free bytes and 7MB until OOM"
10-07 19:27:18.195 14925-14925/com.myapp.hotel E/art: Throwing OutOfMemoryError "Failed to allocate a 10109874 byte allocation with 8141862 free bytes and 7MB until OOM"
10-07 19:27:18.195 14925-14925/com.myapp.hotel E/MessageQueue-JNI: java.lang.StackOverflowError: stack size 8MB
10-07 19:27:19.695 14925-14925/com.myapp.hotel E/art: Throwing OutOfMemoryError "Failed to allocate a 10735842 byte allocation with 7722526 free bytes and 7MB until OOM"
10-07 19:27:20.255 14925-14925/? E/art: Throwing OutOfMemoryError "Failed to allocate a 10735842 byte allocation with 7722654 free bytes and 7MB until OOM"
Что я упускаю / делаю не так?
Обновить
Все мои изображения общим весом ~ 400 КБ. 8 изображений размером около 50 Кб каждое. Проблема в том, что даже если я закомментирую всю загрузку изображения и просто загружу текст, при нажатии на любой элемент listview выдается та же ошибка. Так что это определенно не имеет ничего общего с изображениями. Я думаю, что что-то не так с адаптером.. просто не могу понять, что это может быть! Это просто простой адаптер!
Комментарии:
1. MessageQueue больше похоже на утечку обработчика.
Ответ №1:
Я думаю, что это не имеет ничего общего с обработкой изображений. Это переполнение стека из-за бесконечной рекурсии в getItemId()
@Override
public long getItemId(int i) {
// calls itself with the same value, it can not end well !
return menuSections.indexOf(getItemId(i));
}
Комментарии:
1. БОЖЕ.. Большое вам спасибо 🙂
Ответ №2:
Вы можете использовать largeheap="true"
в Android-манифесте внутри тега приложения. Но лучше изменить размер изображения.
Сколько составляет высота, ширина вашего отдельного изображения?