I have a listview which is showing some images. To avoid UI blocks, I tried to lazy load the thumbnails with an asyncTask in my adapter since that seemed the best solution I found here on SO.
This listView has also an onItemclick and an onItemLongClick listeners.
For some reason, my app is getting really slow down, expecially after performing an onlongclick action. The only thing I found unusual is that my ListView is calling the getView method in loop, never stopping.
Some code:
Adapter
public class FotoGridAdapter extends ArrayAdapter {
private Context context;
private int layoutResourceId;
private ArrayList<WorkorderPicture> workorderPictures = new ArrayList<WorkorderPicture>();
public FotoGridAdapter(Context context, int layoutResourceId, List<WorkorderPicture> pictures) {
super(context, layoutResourceId, pictures);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.workorderPictures = new ArrayList<>(pictures);
}
#Override
#Nullable
public WorkorderPicture getItem(int position) {
return workorderPictures.get(position);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ViewHolder holder;
if (row == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new ViewHolder();
holder.imageTitle = row.findViewById(R.id.text);
holder.image = row.findViewById(R.id.image);
row.setTag(holder);
} else {
holder = (ViewHolder) row.getTag();
}
WorkorderPicture workorderPicture = workorderPictures.get(position);
if (workorderPicture != null) {
String text = workorderPicture.getTITLE();
if (workorderPicture.getPHOTODATE() != null) {
text += " - ";
text += new SimpleDateFormat("dd/MM/yyyy", Locale.getDefault()).format(workorderPicture.getPHOTODATE());
}
holder.imageTitle.setText(text);
String format = AttachmentUtils.getExtensionFromFileName(workorderPicture.getFILE_NAME_WITH_EXTENSION());
if (format == null)
format = "default";
switch (format.toLowerCase()) {
case "image/jpeg":
case "image/png":
if (workorderPicture.getPHOTOSTREAM() != null) {
new ImageGridHandler(context, holder.image, workorderPicture.getPHOTOSTREAM(), workorderPicture.getPHOTOSTREAM().length).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
// holder.image.setImageBitmap(sbm);
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
holder.image.setImageDrawable(getContext().getDrawable(R.drawable.ic_image));
} else {
holder.image.setImageDrawable(getContext().getResources().getDrawable(R.drawable.ic_image));
}
}
break;
case "application/pdf":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
holder.image.setImageDrawable(getContext().getDrawable(R.drawable.ic_pdf));
} else {
holder.image.setImageDrawable(getContext().getResources().getDrawable(R.drawable.ic_pdf));
}
break;
default:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
holder.image.setImageDrawable(getContext().getDrawable(R.drawable.ic_empty_image));
} else {
holder.image.setImageDrawable(getContext().getResources().getDrawable(R.drawable.ic_empty_image));
}
break;
}
}
return row;
}
static class ViewHolder {
TextView imageTitle;
ImageView image;
}
class ImageGridHandler extends AsyncTask<String, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private Context context;
private byte[] photoStream;
private int length;
public ImageGridHandler(Context context, ImageView img, byte[] photoStream, int length) {
imageViewReference = new WeakReference<>(img);
this.context = context;
this.photoStream = photoStream;
this.length = length;
}
#Override
protected Bitmap doInBackground(String... params) {
Bitmap bm = BitmapFactory.decodeByteArray(photoStream, 0, length);
return ThumbnailUtils.extractThumbnail(bm, 80, 100);
}
#Override
protected void onPostExecute(Bitmap result) {
final ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(result);
FotoGridAdapter.this.notifyDataSetChanged();
}
this.cancel(true);
}
}
}
Listeners
gridView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener()
{
#Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view,
final int position, long l) {
AlertDialog.Builder builder = new AlertDialog.Builder(getContext(), R.style.myAlertDialogTheme)
.setNegativeButton("Annulla", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
})
.setPositiveButton("Elimina", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
final String wpID = openedIntervention.getWorkorderPictures().get(position).getID();
realm.executeTransactionAsync(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
realm.where(WorkorderPicture.class).equalTo("ID", wpID).findFirst().setDELETED(true);
}
}, new Realm.Transaction.OnSuccess() {
#Override
public void onSuccess() {
openedIntervention.setWorkorderPictures(realm.where(WorkorderPicture.class)
.equalTo("WORKORDER_ID", openedIntervention.getWorkorder()
.getID())
.equalTo("DELETED", false)
.findAll());
loadData();
}
}, new Realm.Transaction.OnError() {
#Override
public void onError(Throwable error) {
}
});
}
}).setTitle(app_name)
.setMessage("Eliminare l'allegato selezionato?");
builder.show();
return true;
}
});
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, final int position,
long id) {
//code to show a preview
}});
Another info might be that I use Realm, but my pictures are unlinked from it, so I don't think it matter
AsyncTask is asynchronous and after every completion of task, your are notifying the adapter which is causing the data change event so
#Override
protected void onPostExecute(Bitmap result) {
final ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(result);
// FotoGridAdapter.this.notifyDataSetChanged();
// ^^^^^^^^^^^^^^^^ remove this
// not required in case of change in imageview
}
this.cancel(true);
}
Related
According to my app requirement I am showing a row with textbox,imageview and image capture button in a listview. I am capturing an image and immediately saving that image in that realm row. Then adapter loads that image from related realm object when adaoter getview method gets called.
My problem is when the row data for each list is blank, has more than 4 rows and capturing any image; captured image gets loaded in several position along with the position it is meant to be.
For example if I take image for position 0 it shows after scrolling in position 5,then again reloads to position 6. I have noticed that since after scrolling from position 0 to position 6 adapter position returns 0 again. Which is the reason of the image reloading during scrolling in other positions. When I click in any button for either taking picture/text input this reloaded row again returns to proper position.
I went through almost all possible suggested SO questions related to issue imageview shuffling in listview but none of them works for me.Could you suggest any solution to this problem.
My Adapter code is below-
public class ProgressImageAdapter extends RealmBaseAdapter<ImageCommentRealm> implements ListAdapter {
private Context mContext;
String categoryName;
ProgressListener progressListener;
PopAlertDialog alertDialog;
boolean fromHistory;
public ProgressImageAdapter(Context context, OrderedRealmCollection<ImageCommentRealm> data, ProgressListener progressListener, boolean fromHistory) {
super(context, data);
this.mContext = context;
this.progressListener = progressListener;
FragmentActivity activity = (FragmentActivity) (context);
alertDialog = PopAlertDialog.createAlert(activity.getSupportFragmentManager());
this.fromHistory = fromHistory;
}
#Override
public void updateData(OrderedRealmCollection<ImageCommentRealm> data) {
super.updateData(data);
}
public void resetListener() {
this.progressListener = null;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
#Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.image_comment_list_item, parent, false);
holder = new ViewHolder();
holder.textView = (TextView) convertView.findViewById(R.id.tv_title);
holder.editText = (TextView) convertView.findViewById(R.id.et_comment);
holder.imageView = (ImageView) convertView.findViewById(R.id.iv_camera_holder);
holder.imageButton = (ImageButton) convertView.findViewById(R.id.imgbtn_camera);
holder.btnDone = (Button) convertView.findViewById(R.id.btn_confirm);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
final ImageCommentRealm imageCommentRealm = getItem(position);
holder.textView.setText(String.format(Locale.getDefault(), "%s %d %2s %2s", mContext.getResources().getString(R.string.photo), position + 1, mContext.getString(R.string.of), categoryName));
if (Validator.blankCheck(imageCommentRealm.getFile_path()))
loadImage(holder.imageView, imageCommentRealm.getFile_path());
if (Validator.blankCheck(imageCommentRealm.getDesc()))
holder.editText.setText(imageCommentRealm.getDesc());
if (!fromHistory) {
holder.imageButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
((MainActivity) mContext).pickFromCamera();
((MainActivity) mContext).setPicker(new IPhotoPicker() {
#Override
public void setImageUri(String filePath) {
//loadImage(holder,filePath);
saveData(null, filePath, imageCommentRealm.getPk());
}
});
}
});
holder.editText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String title = String.format(Locale.getDefault(), "%s %d %2s %2s", mContext.getResources().getString(R.string.description), position + 1, mContext.getString(R.string.of), categoryName);
alertDialog.showSingleInput(title, imageCommentRealm.getDesc(), imageCommentRealm.getPk(), new SingleInput.Listener() {
#Override
public void onClickGreen(String message, long id) {
if (Validator.blankCheck(message)) saveData(message, null, id);
}
});
}
});
}
return convertView;
}
protected void loadImage(ImageView imageView, String imgPath) {
if (imgPath.startsWith("http")) {
ImageUtility.loadProduct(mContext, imgPath, imageView, R.drawable.home);
} else {
try {
File image_file = new File(imgPath);
if (image_file.exists()) {
Bitmap image_profile = BitmapFactory.decodeFile(image_file.getAbsolutePath());
imageView.setImageBitmap(image_profile);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void saveData(final String comment, final String filepath, final long pk) {
final Realm realm = Realm.getInstance(RealmUtility.getRealmConfig(mContext));
//ImageCommentRealm imageRealm = getItem(position);
//final long pk = imageRealm.getPk();
realm.executeTransactionAsync(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
ImageCommentRealm imageCommentRealm = realm.where(ImageCommentRealm.class).equalTo("pk", pk).findFirst();
if (imageCommentRealm != null && imageCommentRealm.isLoaded()) {
if (Validator.blankCheck(comment)) {
imageCommentRealm.setDesc(comment);
}
if (Validator.blankCheck(filepath)) {
imageCommentRealm.setFile_path(filepath);
}
}
}
}, new Realm.Transaction.OnSuccess() {
#Override
public void onSuccess() {
//notifyDataSetChanged();
realm.close();
try {
if (adapterData != null && adapterData.size() > 0) {
long count = adapterData.where().isNotNull("file_path").isNotNull("desc").count();
if (count == adapterData.size()) {
if (progressListener != null) progressListener.hasRequiredImage();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}, new Realm.Transaction.OnError() {
#Override
public void onError(Throwable error) {
error.printStackTrace();
realm.close();
}
});
}
static class ViewHolder {
TextView textView;
TextView editText;
ImageView imageView;
ImageButton imageButton;
Button btnDone;
}
}
Here is a screenshot after taking picture in first position and then scrolling to bottom
FYI: Testing device 4" Samsung J1 Nxt
Eh, this has nothing to do with Realm, you should clear the image if the image path is null.
if (Validator.blankCheck(imageCommentRealm.getFile_path())) {
loadImage(holder.imageView, imageCommentRealm.getFile_path());
} else {
holder.imageView.setImageBitmap(null);
}
if (Validator.blankCheck(imageCommentRealm.getDesc()))
holder.editText.setText(imageCommentRealm.getDesc());
} else {
holder.editText.setText("");
}
I have a gridview with an adapter, which also has a checkbox look to be shown when an imageview has been clicked. But something goes wrong. If an image is checked and you scroll to the bottom, one of the images are also checked. If you scroll up again, another image than the one you clicked to begin with, is checked (in most cases).
So here is the code for my adapter. The code in concern is the getView method:
public class ImageAdapter extends BaseAdapter {
private Context context;
private ArrayList<String> files;
private Bitmap mPlaceHolderBitmap;
private File directory;
private int thumbSize;
private GridImageListener gridImageListener;
private LayoutInflater inflater;
private View rootView;
private final int MAX_PICTURE_LIMIT = 5;
private int picturesChosenCount = 0;
public ImageAdapter(Context context, ArrayList<String> files, File directory, int thumbSize, GridImageListener gridImageListener, LayoutInflater inflater, View rootView) {
super();
this.context = context;
this.files = files;
this.directory = directory;
this.thumbSize = thumbSize;
this.gridImageListener = gridImageListener;
this.inflater = inflater;
this.rootView = rootView;
mPlaceHolderBitmap = drawableToBitmap(context.getResources().getDrawable(R.drawable.logo));
}
public Bitmap drawableToBitmap (Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable)drawable).getBitmap();
}
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
#Override
public int getCount() {
return files.size();
}
#Override
public Object getItem(int position) {
return files.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup container) {
final ViewHolder holder;
if (convertView == null) { // if it's not recycled, initialize some attributes
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.component_imageview_checkable, null);
holder.imageview = (ImageView) convertView.findViewById(R.id.checkableImageView);
holder.imageview.getLayoutParams().height = thumbSize;
holder.imageview.getLayoutParams().width = thumbSize;
holder.imageCheckBox = (RelativeLayout) convertView.findViewById(R.id.image_check_view);
loadBitmap(files.get(position), holder.imageview);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.imageCheckBox.setId(position);
holder.imageview.setId(position);
holder.imageview.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (holder.imageCheckBox.getVisibility() == View.VISIBLE) {
holder.imageCheckBox.setVisibility(View.INVISIBLE);
picturesChosenCount--;
} else {
if (picturesChosenCount < 5) {
holder.imageCheckBox.setVisibility(View.VISIBLE);
picturesChosenCount++;
} else {
Toast.makeText(context, "Max number of pictures has been reached", Toast.LENGTH_SHORT).show();
}
}
gridImageListener.onClickImage(files.get(position));
}
});
holder.id = position;
return convertView;
}
public void loadBitmap(String path, ImageView imageView) {
if (cancelPotentialWork(path, imageView)) {
final BitmapWorkerTask task = new BitmapWorkerTask(imageView, context, path, directory, thumbSize);
final AsyncDrawable asyncDrawable =
new AsyncDrawable(context.getResources(), mPlaceHolderBitmap, task);
imageView.setImageDrawable(asyncDrawable);
task.execute(path);
}
}
public static boolean cancelPotentialWork(String path, ImageView imageView) {
final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
if (bitmapWorkerTask != null) {
final String bitmapData = bitmapWorkerTask.path;
// If bitmapData is not yet set or it differs from the new data
if (bitmapData.equals("0") || !bitmapData.equals(path)) {
// Cancel previous task
bitmapWorkerTask.cancel(true);
} else {
// The same work is already in progress
return false;
}
}
// No task associated with the ImageView, or an existing task was cancelled
return true;
}
private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {
if (imageView != null) {
final Drawable drawable = imageView.getDrawable();
if (drawable instanceof AsyncDrawable) {
final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
return asyncDrawable.getBitmapWorkerTask();
}
}
return null;
}
static class AsyncDrawable extends BitmapDrawable {
private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;
public AsyncDrawable(Resources res, Bitmap bitmap,
BitmapWorkerTask bitmapWorkerTask) {
super(res, bitmap);
bitmapWorkerTaskReference =
new WeakReference<BitmapWorkerTask>(bitmapWorkerTask);
}
public BitmapWorkerTask getBitmapWorkerTask() {
return bitmapWorkerTaskReference.get();
}
}
}
class ViewHolder {
int id;
ImageView imageview;
RelativeLayout imageCheckBox;
}
I know it has something to do with the recycling of views in the gridview, but I don't know how to avoid/fix it. Each imageview is loaded separately in an asynctask and is reloaded when you scroll to it. If you need to take a look at it, the code is here: http://pastebin.com/2BcBW7PN
And finally, here is my XML for the item of each image:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/checkableImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<RelativeLayout
android:id="#+id/image_check_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/checkableImageView"
android:layout_alignTop="#+id/checkableImageView"
android:layout_alignRight="#+id/checkableImageView"
android:layout_alignBottom="#+id/checkableImageView"
android:visibility="invisible">
<com.ivankocijan.magicviews.views.MagicTextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="#color/white"
android:background="#drawable/blue_border"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<com.ivankocijan.magicviews.views.MagicTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/icon_check"
android:textColor="#color/white"
android:textSize="#dimen/txtsize_standard_smaller_icon"
android:padding="4dp"
app:typeFace="#string/icon_font"
android:background="#color/standard_blue"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
</RelativeLayout>
</RelativeLayout>
What might be wrong? I have read all the tutorials I could find, but none of them seemed to do any difference.
You can use : Eg: Android – Select multiple photos from Gallery
Or :
Entity -CustomGallery.class
public class CustomGallery {
public String sdcardPath;
public boolean isSeleted = false;
}
Adapter -GalleryAdapterCustom.class
private Context mContext;
private LayoutInflater infalter;
private ArrayList<CustomGallery> data = new ArrayList<CustomGallery>();
ImageLoader imageLoader;
private boolean isActionMultiplePick;
public GalleryAdapterCustom(Context c, ImageLoader imageLoader) {
infalter = (LayoutInflater) c
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mContext = c;
this.imageLoader = imageLoader;
// clearCache();
}
#Override
public int getCount() {
return data.size();
}
#Override
public CustomGallery getItem(int position) {
return data.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public void setMultiplePick(boolean isMultiplePick) {
this.isActionMultiplePick = isMultiplePick;
}
public void selectAll(boolean selection) {
for (int i = 0; i < data.size(); i++) {
data.get(i).isSeleted = selection;
}
notifyDataSetChanged();
}
public boolean isAllSelected() {
boolean isAllSelected = true;
for (int i = 0; i < data.size(); i++) {
if (!data.get(i).isSeleted) {
isAllSelected = false;
break;
}
}
return isAllSelected;
}
public boolean isAnySelected() {
boolean isAnySelected = false;
for (int i = 0; i < data.size(); i++) {
if (data.get(i).isSeleted) {
isAnySelected = true;
break;
}
}
return isAnySelected;
}
public ArrayList<CustomGallery> getSelected() {
ArrayList<CustomGallery> dataT = new ArrayList<CustomGallery>();
for (int i = 0; i < data.size(); i++) {
if (data.get(i).isSeleted) {
dataT.add(data.get(i));
}
}
return dataT;
}
public void addAll(ArrayList<CustomGallery> files) {
try {
this.data.clear();
this.data.addAll(files);
} catch (Exception e) {
e.printStackTrace();
}
notifyDataSetChanged();
}
public void changeSelection(View v, int position) {
if (data.get(position).isSeleted) {
data.get(position).isSeleted = false;
} else {
data.get(position).isSeleted = true;
}
ArrayList<CustomGallery> dataT = new ArrayList<CustomGallery>();
for (int i = 0; i < data.size(); i++) {
if (data.get(i).isSeleted) {
dataT.add(data.get(i));
}
}
if (dataT.size() > NewPostActivity.max_image) {
Toast.makeText(mContext, "Bạn chỉ được đăng tối đa 20 ảnh / 1 tin",
Toast.LENGTH_SHORT).show();
data.get(position).isSeleted = false;
}
((ViewHolder) v.getTag()).imgQueueMultiSelected.setSelected(data
.get(position).isSeleted);
// }
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
convertView = infalter.inflate(R.layout.gallery_item, null);
holder = new ViewHolder();
holder.imgQueue = (ImageView) convertView
.findViewById(R.id.imgQueue);
holder.imgQueueMultiSelected = (ImageView) convertView
.findViewById(R.id.imgQueueMultiSelected);
if (isActionMultiplePick) {
holder.imgQueueMultiSelected.setVisibility(View.VISIBLE);
} else {
holder.imgQueueMultiSelected.setVisibility(View.GONE);
}
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.imgQueue.setTag(position);
try {
imageLoader.displayImage("file://" + data.get(position).sdcardPath,
holder.imgQueue, new SimpleImageLoadingListener() {
#Override
public void onLoadingStarted(String imageUri, View view) {
holder.imgQueue
.setImageResource(R.drawable.default_icon2);
super.onLoadingStarted(imageUri, view);
}
});
if (isActionMultiplePick) {
holder.imgQueueMultiSelected
.setSelected(data.get(position).isSeleted);
}
} catch (Exception e) {
e.printStackTrace();
}
return convertView;
}
public class ViewHolder {
ImageView imgQueue;
ImageView imgQueueMultiSelected;
}
public void clearCache() {
imageLoader.clearDiscCache();
imageLoader.clearMemoryCache();
}
public void clear() {
data.clear();
notifyDataSetChanged();
}
}
Activity- CustomGalleryActivity.class
public class CustomGalleryActivity extends Activity {
GridView gridGallery;
Handler handler;
GalleryAdapterCustom adapter;
String count_image;
RelativeLayout layout_select, layout_cancel;
ImageView imgNoMedia;
Button btnGalleryOk;
public static final int REQUEST_CODE_Gallery = 1111;
public static final int REQUEST_CODE_Gallery_OK = 2222;
String action;
private ImageLoader imageLoader;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.gallery);
action = getIntent().getStringExtra("action");
if (action == null) {
finish();
}
initImageLoader();
init();
}
private void initImageLoader() {
try {
String CACHE_DIR = Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/.temp_tmp";
new File(CACHE_DIR).mkdirs();
File cacheDir = StorageUtils.getOwnCacheDirectory(getBaseContext(),
CACHE_DIR);
DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
.cacheOnDisc(true).imageScaleType(ImageScaleType.EXACTLY)
.bitmapConfig(Bitmap.Config.RGB_565).build();
ImageLoaderConfiguration.Builder builder = new ImageLoaderConfiguration.Builder(
getBaseContext())
.defaultDisplayImageOptions(defaultOptions)
.discCache(new UnlimitedDiscCache(cacheDir))
.memoryCache(new WeakMemoryCache());
ImageLoaderConfiguration config = builder.build();
imageLoader = ImageLoader.getInstance();
imageLoader.init(config);
} catch (Exception e) {
}
}
private void init() {
handler = new Handler();
gridGallery = (GridView) findViewById(R.id.gridGallery);
gridGallery.setFastScrollEnabled(true);
adapter = new GalleryAdapterCustom(getApplicationContext(), imageLoader);
PauseOnScrollListener listener = new PauseOnScrollListener(imageLoader,
true, true);
gridGallery.setOnScrollListener(listener);
if (action.equalsIgnoreCase(Action.ACTION_MULTIPLE_PICK)) {
findViewById(R.id.layout_select).setVisibility(View.VISIBLE);
gridGallery.setOnItemClickListener(mItemMulClickListener);
adapter.setMultiplePick(true);
} else if (action.equalsIgnoreCase(Action.ACTION_PICK)) {
findViewById(R.id.layout_select).setVisibility(View.GONE);
gridGallery.setOnItemClickListener(mItemSingleClickListener);
adapter.setMultiplePick(false);
}
gridGallery.setAdapter(adapter);
imgNoMedia = (ImageView) findViewById(R.id.imgNoMedia);
layout_cancel = (RelativeLayout) findViewById(R.id.layout_cancel);
layout_cancel.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
finish();
}
});
layout_select = (RelativeLayout) findViewById(R.id.layout_select);
layout_select.setOnClickListener(mOkClickListener);
new Thread() {
#Override
public void run() {
Looper.prepare();
handler.post(new Runnable() {
#Override
public void run() {
adapter.addAll(getGalleryPhotos());
checkImageStatus();
}
});
Looper.loop();
};
}.start();
}
private void checkImageStatus() {
if (adapter.isEmpty()) {
imgNoMedia.setVisibility(View.VISIBLE);
} else {
imgNoMedia.setVisibility(View.GONE);
}
}
View.OnClickListener mOkClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
ArrayList<CustomGallery> selected = adapter.getSelected();
String[] allPath = new String[selected.size()];
for (int i = 0; i < allPath.length; i++) {
allPath[i] = selected.get(i).sdcardPath;
}
if (allPath.length == 0) {
Toast.makeText(CustomGalleryActivity.this, "Vui lòng chọn ảnh",
Toast.LENGTH_SHORT).show();
} else {
Intent data = new Intent().putExtra("all_path", allPath);
setResult(REQUEST_CODE_Gallery_OK, data);
finish();
}
}
};
AdapterView.OnItemClickListener mItemMulClickListener = new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> l, View v, int position, long id) {
adapter.changeSelection(v, position);
}
};
AdapterView.OnItemClickListener mItemSingleClickListener = new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> l, View v, int position, long id) {
CustomGallery item = adapter.getItem(position);
Intent data = new Intent().putExtra("single_path", item.sdcardPath);
setResult(REQUEST_CODE_Gallery_OK, data);
finish();
}
};
private ArrayList<CustomGallery> getGalleryPhotos() {
ArrayList<CustomGallery> galleryList = new ArrayList<CustomGallery>();
try {
final String[] columns = { MediaStore.Images.Media.DATA,
MediaStore.Images.Media._ID };
final String orderBy = MediaStore.Images.Media._ID;
Cursor imagecursor = managedQuery(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns,
null, null, orderBy);
if (imagecursor != null && imagecursor.getCount() > 0) {
while (imagecursor.moveToNext()) {
CustomGallery item = new CustomGallery();
int dataColumnIndex = imagecursor
.getColumnIndex(MediaStore.Images.Media.DATA);
item.sdcardPath = imagecursor.getString(dataColumnIndex);
galleryList.add(item);
}
}
} catch (Exception e) {
e.printStackTrace();
}
// show newest photo at beginning of the list
Collections.reverse(galleryList);
return galleryList;
}
Use .
Intent i = new Intent(NewPostActivity.this,
CustomGalleryActivity.class);
i.putExtra("action", Action.ACTION_MULTIPLE_PICK);
startActivityForResult(i, REQUEST_CODE_Gallery);
In my app I'm showing data in listview. While scrolling through listview my app is crashing. What changes should I make?
as given in the error my RecipeListFragment.java file is:
public class RecipeListFragment extends Fragment {
MyDatabase db;
boolean isfav = false;
Context context;
ListView lvrecipe;
ArrayList<RecipePojo> recipelist = new ArrayList<RecipePojo>();
LinearLayout ll;
DisplayImageOptions options;
private ProgressDialog progress;
int position;
String recipeid;
int checkcounter = 0;
private Custom_Adapter adapter;
public RecipeListFragment() {
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_recipe_list_actvity, container, false);
context = getActivity();
lvrecipe = (ListView) rootView.findViewById(R.id.lvrecipe);
// adView = (MoPubView)rootView. findViewById(R.id.mopub_sample_ad);
new getrecipe().execute();
db = new MyDatabase(getActivity());
// recipelist = DataManager.recipelist;
position = DataManager.selectedposition;
adapter = new Custom_Adapter(getActivity());
adapter.notifyDataSetChanged();
lvrecipe.setAdapter(adapter);
/* if(recipeid!=null){
checkcounter = db.checkrecipefav(recipeid);
}
if (checkcounter > 0) {
isfav = true;
} else {
isfav = false;
}
db.close();*/
lvrecipe.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
DataManager.selectedposition = position;
Intent i = new Intent(getActivity(), RecipeDescription.class);
i.putExtra("cusinename", DataManager.cusinename);
startActivity(i);
getActivity().finish();
}
});
// adddisplay();
return rootView;
}
#Override
public void onResume() {
super.onResume();
}
public class Custom_Adapter extends BaseAdapter {
private LayoutInflater mInflater;
public Custom_Adapter(Context c) {
mInflater = LayoutInflater.from(c);
}
#Override
public int getCount() {
if (recipelist != null) {
return recipelist.size();
} else {
return 0;
}
}
#Override
public Object getItem(int position) {
if (recipelist != null) {
return recipelist.get(position);
} else {
return 0;
}
}
#Override
public long getItemId(int position) {
if (recipelist != null) {
return position;
} else {
return 0;
}
}
#SuppressWarnings("deprecation")
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.recipelist, null);
holder = new ViewHolder();
holder.txttile = (TextView) convertView.findViewById(R.id.txttile);
holder.imgrecipe = (ImageView) convertView.findViewById(R.id.imgrecipe);
holder.fav_unfav = (ImageView) convertView.findViewById(R.id.fav_unfav);
holder.ratingbar = (RatingBar) convertView.findViewById(R.id.ratingbar);
holder.txtduration = (TextView) convertView.findViewById(R.id.txtduration);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
if (recipelist != null) {
recipeid = recipelist.get(position).getRecipeid();
checkcounter = db.checkrecipefav(recipeid);
}
if (checkcounter > 0) {
isfav = true;
} else {
isfav = false;
}
db.close();
if (isfav) {
holder.fav_unfav.setImageResource(R.drawable.favourite);
} else {
holder.fav_unfav.setImageResource(R.drawable.favourites);
}
Typeface face1 = Typeface.createFromAsset(getActivity().getAssets(), "sinkin_sans_300_light.ttf");
Typeface face2 = Typeface.createFromAsset(getActivity().getAssets(), "sinkin_sans_400_regular.ttf");
holder.txttile.setTypeface(face2);
holder.txtduration.setTypeface(face1);
holder.txttile.setText(recipelist.get(position).getRecipename());
try {
String[] prep = recipelist.get(position).getPrep_time().split(" ");
String[] cook = recipelist.get(position).getCooking_time().split(" ");
int totalTime = Integer.parseInt(prep[0]) + Integer.parseInt(cook[0]);
holder.txtduration.setText(""+totalTime+" min");
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
String url = DataManager.photourl + "recipe/" + recipelist.get(position).getRecipeid() + ".jpg";
try {
url = URLDecoder.decode(url, "UTF-8");
url = url.replaceAll(" ", "%20");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
if (recipelist.get(position).getVideo_link().equals("none")) {
// holder.imgvideo.setVisibility(View.GONE);
}
String rating = recipelist.get(position).getRatings();
if (rating != null && rating.trim().length() > 0) {
holder.ratingbar.setRating(Float.valueOf(rating));
}
//holder.imgrecipe.setImage(url,getResources().getDrawable(R.drawable.cusine));
if (holder.imgrecipe != null) {
if (url != null && url.trim().length() > 0) {
//final ProgressBar pbar = holder.pbar;
final ImageView imageView = holder.imgrecipe;
//final RelativeLayout imgRL = holder.imageRL;
ImageLoader.getInstance().displayImage(url, holder.imgrecipe, options, new SimpleImageLoadingListener() {
#Override
public void onLoadingComplete(String imageUri,
View view, Bitmap loadedImage) {
super.onLoadingComplete(imageUri, view, loadedImage);
imageView.setAdjustViewBounds(true);
}
#Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
super.onLoadingFailed(imageUri, view, failReason);
}
#Override
public void onLoadingStarted(String imageUri, View view) {
super.onLoadingStarted(imageUri, view);
}
});
} else {
}
}
return convertView;
}
class ViewHolder {
TextView txttile, txtduration;
ImageView imgrecipe;
ImageView fav_unfav;
RatingBar ratingbar;
}
}
public class getrecipe extends AsyncTask<String, Void, String> {
boolean response = false;
#Override
protected void onPreExecute() {
//progress = ProgressDialog.show(context, "Getting Data...","Please wait....");
progress = new ProgressDialog(getActivity());
progress.setMessage("Please wait....");
progress.show();
}
#Override
protected String doInBackground(String... params) {
response = APIManager.getrecipebycusine(DataManager.CUISINE_ID);
return "";
}
#Override
protected void onPostExecute(String result) {
progress.cancel();
if (response) {
if (DataManager.status.equalsIgnoreCase("1")) {
recipelist = DataManager.recipelist;
adapter.notifyDataSetChanged();
//Intent i = new Intent(getActivity(),RecipeListActvity.class);
//startActivity(i);
} else {
connectionerror();
}
} else {
connectionerror();
}
}
#Override
protected void onProgressUpdate(Void... values) {
}
}
public void alert() {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(getActivity());
alertDialog.setTitle("No Recipe!");
alertDialog.setMessage("No Recipe for this Cusine");
alertDialog.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
});
alertDialog.show();
}
private static class AnimateFirstDisplayListener extends SimpleImageLoadingListener {
static final List<String> displayedImages = Collections.synchronizedList(new LinkedList<String>());
#Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
if (loadedImage != null) {
ImageView imageView = (ImageView) view;
boolean firstDisplay = !displayedImages.contains(imageUri);
if (firstDisplay) {
FadeInBitmapDisplayer.animate(imageView, 500);
displayedImages.add(imageUri);
}
}
}
}
public void connectionerror() {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(getActivity());
alertDialog.setTitle("Error!");
alertDialog.setMessage("Connection Lost ! Try Again");
alertDialog.setPositiveButton("Retry",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
new getrecipe().execute();
}
});
alertDialog.show();
}}
The errors that are showing in Crashlytics is:
Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources$Theme android.content.Context.getTheme()' on a null object reference
at android.app.AlertDialog.resolveDialogTheme(AlertDialog.java:154)
at android.app.AlertDialog$Builder.<init>(AlertDialog.java:379)
at com.raccoonfinger.salad.RecipeListFragment.connectionerror(RecipeListFragment.java:381)
at com.raccoonfinger.salad.RecipeListFragment$getrecipe.onPostExecute(RecipeListFragment.java:335)
at com.raccoonfinger.salad.RecipeListFragment$getrecipe.onPostExecute(RecipeListFragment.java:296)
at android.os.AsyncTask.finish(AsyncTask.java:632)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5312)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696)
Please do not use getActivity() directly in Fragment because sometimes it returns null..
Always pass activity as a parameter in constructor..!!
Please use below method to create your Fragment and use activity reference instead of getActivity()..
public static AboutFragment newInstance(Activity activity) {
AboutFragment aboutFragment = new AboutFragment();
aboutFragment.mActivity = activity;
return aboutFragment;
}
Hope it will help.
Thanks ..!!
Hi,
I try to refresh my data with a tweet app which I am making. When I delete a following person by cliking on the button "following_del", I want that my list view being refreshed without the user I just deleted. Do you have any idea do to this? I am in a baseAdaptor class. Thanks
public class UsersAdapter extends BaseAdapter implements DialogInterface.OnShowListener {
private List<User> mUsers;
Integer BUTTON_ACTIVATE = 0;
public List<User> getUsers() {
return mUsers;
}
public Context context;
public void setUsers(List<User> users) {
mUsers = users;
}
public UsersAdapter(Context context) {
this.context = context;
}
#Override
public int getCount() {
return mUsers != null ? mUsers.size() : 0;
}
#Override
public User getItem(int position) {
return mUsers.get(position);
}
#Override
public long getItemId(int position) {
// if (getItem(position).getId() == null) {
return 0;
// } else {
// return getItem(position).getId().hashCode();
// }
}
#Override
public boolean hasStableIds() {
return true;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.follower_item, parent, false);
BUTTON_ACTIVATE = 0;
}
final User user = getItem(position);
TextView handleView = (TextView) convertView.findViewById(R.id.handle);
handleView.setText(user.getHandle());
TextView statusView = (TextView) convertView.findViewById(R.id.status);
Log.i(context.getClass().getName(), "Je suis dans ce context2");
ImageButton button_del = (ImageButton) convertView.findViewById(R.id.add_following);
button_del.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (AccountManager.isConnected(context)) {
new AsyncTask<String, Void, Integer>() {
#Override
protected Integer doInBackground(String... arg) {
try {
String handle = AccountManager.getUserHandle(context);
String token = AccountManager.getUserToken(context);
String content = user.getHandle();
if (handle.compareTo(content) != 0) {
new ApiClient().postdelFollowing(handle, token, content);
return 1;
}
} catch (IOException e) {
return 0;
}
}
#Override
protected void onPostExecute(Integer success) {
if (success == 1) {
Toast.makeText(context, "Vous ne suivez plus " + user.getHandle(), Toast.LENGTH_SHORT).show();
if (context.getClass().getName().compareTo(FollowingActivity.class.getName()) == 0) {
Intent intent = new Intent(context, FollowingActivity.class);
intent.putExtras(FollowingFragment.newArgument(UsersFragment.user));
context.startActivity(intent);
}
} else {
Toast.makeText(context, "Une erreur s'est produite", Toast.LENGTH_SHORT).show();
}
}
}.execute();
} else {
new AlertDialog.Builder(context)
.setMessage("Veuillez vous connecter")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
})
.show();
}
}
});
return convertView;
}
}
This question already exists:
OnListItemClick event is not working
Closed 8 years ago.
I have been facing a problem...there is a five different Java classes MainActivity, Application, ApplicationAdapter, FetchData ,FetchDataListener.. I am binding mysql data from api in ListView... but I am trying to fire a click event on ListView but I am getting error....here is code...
MainActivity.java
#Override
public void onFetchComplete(List<Applicity> data) {
// dismiss the progress dialog
if(dialog != null) dialog.dismiss();
// create new adapter
ApplicationAdapter adapter = new ApplicationAdapter(this, data);
// set the adapter to list
setListAdapter(adapter);
}
public void onListItemClick(ListView l, View v, int position, long id) {
Applicity app= new Applicity();
int p =app.getPosition(position);
Toast.makeText(this,p,Toast.LENGTH_LONG).show();
}
ApplicationAdapter.java
public class ApplicationAdapter extends ArrayAdapter<Applicity>{
private List<Applicity> items;
public ApplicationAdapter(Context context, List<Applicity> items) {
super(context, R.layout.app_custom_list, items);
this.items = items;
}
#Override
public int getCount() {
return items.size();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if(v == null) {
LayoutInflater li = LayoutInflater.from(getContext());
v = li.inflate(R.layout.app_custom_list, null);
}
Applicity app = items.get(position);
if(app != null) {
ImageView icon = (ImageView)v.findViewById(R.id.appIcon);
TextView titleText = (TextView)v.findViewById(R.id.titleTxt);
LinearLayout ratingCntr = (LinearLayout)v.findViewById(R.id.ratingCntr);
TextView dlText = (TextView)v.findViewById(R.id.dlTxt);
if(icon != null) {
Resources res = getContext().getResources();
String sIcon = "com.sj.jsondemo:drawable/" + app.getIcon();
icon.setImageDrawable(res.getDrawable(res.getIdentifier(sIcon, null, null)));
}
if(titleText != null) titleText.setText(app.getTitle());
if(dlText != null) {
NumberFormat nf = NumberFormat.getNumberInstance();
dlText.setText(nf.format(app.getTotalDl())+" dl");
}
if(ratingCntr != null && ratingCntr.getChildCount() == 0) {
/*
* max rating: 5
*/
for(int i=1; i<=5; i++) {
ImageView iv = new ImageView(getContext());
if(i <= app.getRating()) {
iv.setImageDrawable(getContext().getResources().getDrawable(R.drawable.start_checked));
}
else {
iv.setImageDrawable(getContext().getResources().getDrawable(R.drawable.start_unchecked));
}
ratingCntr.addView(iv);
}
}
}
return v;
}
}
Applicity.java
public class Applicity {
private String title;
private long totalDl;
private int rating;
public int position;
private String icon;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public long getTotalDl() {
return totalDl;
}
public void setTotalDl(long totalDl) {
this.totalDl = totalDl;
}
public int getRating() {
return rating;
}
public void setRating(int rating) {
this.rating = rating;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public int getPosition(int arg){
return position;
}
}
Use OnItemClickListener. You're creating a new custom method instead of OnItemClickListener.
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//Do something here.
}
});