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);
Related
I use this code to update the listview of my project but i get duplicates by using the listview.invalidateViews(); method. Also i tried the notifyDataSetChanged method by calling it from the customadapter of mine that extends baseadapter but it does not seem to work properly. I need to update using the postexecute method after downloading the data from online source. Please check below my code.
The HomeFragment
public class HomeFragment extends Fragment {
private HomeViewModel homeViewModel;
Bitmap mIcon12;
private ProgressDialog pDialog;
private ArrayList< String> arrayList;
ArrayList<HashMap<String,String>> aList;
private int scrollState;
private int offset = 0;
private Button btnLoadMore;
private boolean flag = false;
private boolean loadingMore = false;
TextView textinput2;
ImageView lv1;
View root;
View root1;
ProgressBar pb;
private int scrollpos;
private ListView lv;
public ArrayList<SubjectData> arrayList1;
CustomAdapter adapter1;
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container,Bundle savedInstanceState) {
homeViewModel =
new ViewModelProvider(this).get(HomeViewModel.class);
root = inflater.inflate(R.layout.fragment_home, container, false);
root1 = inflater.inflate(R.layout.listitem, container, false);
final TextView textView = root.findViewById(R.id.text_home);
lv = root.findViewById(R.id.homelistview);
lv1=root1.findViewById(R.id.flagimageview);
arrayList1 = new ArrayList<SubjectData>();
lv.setClickable(true);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Object o = lv.getItemAtPosition(position);
Toast.makeText(getContext(), "myPosss "+position, Toast.LENGTH_LONG).show();
}
});
MainActivity main1 = (MainActivity)getActivity();
if (savedInstanceState == null) {
adapter1 = new CustomAdapter(getContext(), arrayList1);
System.out.println("to lv den ine null edopoooooooooooo");
} else {
}
pb = new ProgressBar(getContext());
lv.addFooterView(pb);
lv.setAdapter(adapter1);
if (!flag) {
new loadMoreListView().execute();
flag = true;
System.out.println("to flag1 ine: "+ flag);
}
lv.setOnScrollListener(new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
int totalItemCount) {
scrollpos = totalItemCount;
int lastPos = firstVisibleItem + visibleItemCount;
if ((lastPos == totalItemCount) && (!loadingMore)) {
if (totalItemCount < 250) {
System.out.println("to flag4 ine " + flag);
new loadMoreListView().execute();
} else {
lv.removeFooterView(pb);
}
}
}
});
homeViewModel.getText().observe(getViewLifecycleOwner(), new Observer<String>() {
#Override
public void onChanged(#Nullable String s) {
textView.setText(s);
}
});
return root;
}
private class loadMoreListView extends AsyncTask< Void, Void, String> {
protected String doInBackground(Void... unused) {
loadingMore = true;
String result = null;
String url = "https://api.androidhive.info/json/imdb_top_250.php?offset=" + offset;
try {
URL mUrl = new URL(url);
HttpURLConnection urlConnection = (HttpURLConnection) mUrl.openConnection();
urlConnection.setConnectTimeout(10000); //set timeout to 5 seconds
urlConnection.connect();
InputStream inputStream = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
StringBuffer buffer = new StringBuffer();
String str = "";
while ((str = br.readLine()) != null) {
buffer.append(str);
}
result = buffer.toString();
} catch (Exception e) {
System.out.println("error " + e);
}
return result;
}
/*
* An InputStream that skips the exact number of bytes provided, unless it reaches EOF.
*/
public class FlushedInputStream extends FilterInputStream {
public FlushedInputStream(InputStream inputStream) {
super(inputStream);
}
#Override
public long skip(long n) throws IOException {
long totalBytesSkipped = 0L;
while (totalBytesSkipped < n) {
long bytesSkipped = in.skip(n - totalBytesSkipped);
if (bytesSkipped == 0L) {
int b = read();
if (b < 0) {
break; // we reached EOF
} else {
bytesSkipped = 1; // we read one byte
}
}
totalBytesSkipped += bytesSkipped;
}
return totalBytesSkipped;
}
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
return vi;
}
protected void onPostExecute(String result) {
if (result != null) {
try {
JSONArray array = new JSONArray(result);
for (int i = 0; i < array.length(); i++) {
arrayList1.add(new SubjectData(array.getJSONObject(i).getString("title"),"link", "image"));
}
loadingMore = false;
System.out.println("to flag2 ine: "+ flag);
lv.invalidateViews();
// adapter1.updater(arrayList1);
offset+=20;
} catch (Exception e) {
e.printStackTrace();
}
} else {
if (pb==null)
{
System.out.println("ine null to pb ");
}
else if (lv==null) {
pb.setVisibility(pb.GONE);
Toast.makeText(getContext(), "Please check your internet connection!", Toast.LENGTH_SHORT).show();
pb=null;
}
else
{
lv.removeFooterView(pb);
}
}
}
}
}
And this is the customadapter that extends the baseadapter
public class CustomAdapter extends BaseAdapter {
public ArrayList<SubjectData> arrayList;
Context context;
Thread t;
public CustomAdapter(Context context, ArrayList<SubjectData> arrayList) {
this.context = context;
this.arrayList = arrayList;
}
public void updater(ArrayList<SubjectData> updatedlist)
{
this.arrayList.clear();
this.arrayList.addAll(updatedlist);
this.notifyDataSetChanged();
}
#Override
public boolean areAllItemsEnabled() {
return false;
}
#Override
public boolean isEnabled(int position) {
return true;
}
#Override
public int getCount() {
return arrayList.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public boolean hasStableIds() {
return false;
}
public View getView(int position, View convertView, ViewGroup parent) {
SubjectData subjectData = arrayList.get(position);
if(convertView == null) {
LayoutInflater layoutInflater = LayoutInflater.from(context);
convertView = layoutInflater.inflate(R.layout.listitem, null);
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AppCompatActivity activity= (AppCompatActivity)context;
ImageView image = new ImageView(context);
image.setImageResource(R.drawable.notificationstoreicon);
final ProgressBar pb = new ProgressBar(context);
String[] coupons = {"horse", "cow", "camel", "sheep", "goat"};
AlertDialog.Builder builder =
new AlertDialog.Builder(context).
setTitle("Details").
setView(pb).
setMessage("please wait...")
.
setPositiveButton("Go", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// dialog.dismiss();
if (t.isAlive())
{
}
else
{
}
}
});
AlertDialog dialog1=builder.create();
dialog1.show();
t= new Thread()
{ private volatile boolean running = true;
public void run() {
System.out.println("blah");
while (running) {
try {
// thread to sleep for 1000 milliseconds
Thread.sleep(4000);
running=false;
} catch (Exception e) {
System.out.println(e);
}
}
runOnUiThread(new Runnable() {
#Override
public void run() {
dialog1.setMessage("more details");
pb.setVisibility(View.GONE);
Picasso.get()
.load(subjectData.Image)
.into(image);
dialog1.setContentView(image);
}
});
}
public void stopThread() {
running = false;
interrupt();
}
public void runOnUiThread(Runnable runnable){
final Handler UIHandler = new Handler(Looper.getMainLooper());
UIHandler.post(runnable);
}
};
t.start();
}
});
TextView tittle = convertView.findViewById(R.id.txt);
ImageView imag = convertView.findViewById(R.id.flagimageview);
tittle.setText(subjectData.SubjectName);
Picasso.get()
.load(subjectData.Image)
.into(imag);
}
return convertView;
}
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public int getViewTypeCount() {
if(getCount() > 0){
return arrayList.size();
}else{
return 1;
}
}
#Override
public boolean isEmpty() {
return false;
}
}
Fragment home xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.home.HomeFragment">
<TextView
android:id="#+id/text_home"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="Please check your internet connection!"
android:textAlignment="center"
android:textSize="20sp"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="invisible" />
<ListView
android:id="#+id/homelistview"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="#+id/helloimageview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="productimage"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Any help appreciated. I searched in other people posts but no luck! I have been searching for hours actually!
Can anyone help me? Cant find solution!
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);
}
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 ..!!
I have checked all the related posts so far, but did not managed to fix this "Out of memory on a 1843216-byte allocation" error my GridView activity generates.
Basically this activity displays the images from the phone's gallery in a GridView (as a multiple image picker), at first it loads everything just fine, at the second try I get the memory error and the GridView skips loading some of the image thumbnails.
I have disabled the memory caching by: ".cacheInMemory(false)", and using only disk caching with fixed ImageView width and height, but still got the memory error.
Could someone help me out? Thanks!
The CustomGalleryActivity, showing all pictures on the phone:
public class CustomGalleryActivity extends Activity {
GridView gridGallery;
Handler handler;
GalleryAdapter adapter;
ImageView imgNoMedia;
Button btnGalleryOk;
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().getAction();
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()
.imageScaleType(ImageScaleType.EXACTLY)
.bitmapConfig(Bitmap.Config.RGB_565)
.cacheInMemory(false)
.cacheOnDisk(true)
.considerExifParams(true)
.build();
ImageLoaderConfiguration.Builder builder = new ImageLoaderConfiguration.Builder(getBaseContext())
.threadPriority(Thread.NORM_PRIORITY - 2)
.denyCacheImageMultipleSizesInMemory()
.defaultDisplayImageOptions(defaultOptions)
.discCache(new UnlimitedDiscCache(cacheDir))
.tasksProcessingOrder(QueueProcessingType.LIFO);
//.memoryCache(new WeakMemoryCache());
L.writeLogs(false);
ImageLoaderConfiguration config = builder.build();
imageLoader = ImageLoader.getInstance();
imageLoader.destroy();
imageLoader.init(config);
} catch (Exception e) {
}
}
private void init() {
handler = new Handler();
gridGallery = (GridView) findViewById(R.id.gridGallery);
gridGallery.setFastScrollEnabled(true);
adapter = new GalleryAdapter(getApplicationContext(), imageLoader);
PauseOnScrollListener listener = new PauseOnScrollListener(imageLoader,
true, true);
gridGallery.setOnScrollListener(listener);
if (action.equalsIgnoreCase(Action.ACTION_MULTIPLE_PICK)) {
findViewById(R.id.llBottomContainer).setVisibility(View.VISIBLE);
gridGallery.setOnItemClickListener(mItemMulClickListener);
adapter.setMultiplePick(true);
} else if (action.equalsIgnoreCase(Action.ACTION_PICK)) {
findViewById(R.id.llBottomContainer).setVisibility(View.GONE);
gridGallery.setOnItemClickListener(mItemSingleClickListener);
adapter.setMultiplePick(false);
}
gridGallery.setAdapter(adapter);
imgNoMedia = (ImageView) findViewById(R.id.imgNoMedia);
btnGalleryOk = (Button) findViewById(R.id.btnGalleryOk);
btnGalleryOk.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;
}
Intent data = new Intent().putExtra("all_path", allPath);
setResult(RESULT_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);
if (adapter.getSelected().size() >= 15) {
Toast.makeText(getApplicationContext(), "Max. 15 de poze pot fi selectate o data!", Toast.LENGTH_LONG).show();
} else {
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(RESULT_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;
#SuppressWarnings("deprecation")
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;
}
}
And its CustomAdapter:
public class GalleryAdapter extends BaseAdapter {
private Context mContext;
private LayoutInflater infalter;
private ArrayList<CustomGallery> data = new ArrayList<CustomGallery>();
ImageLoader imageLoader;
private boolean isActionMultiplePick;
public GalleryAdapter(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;
}
((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.no_media);
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();
}
}
Try to do this with Picasso library instead of using image loader library. Hope this may helpful for you.
https://github.com/square/picasso
I have seen other SO questions and already tried their solution's but didn't help so i am myself asking
I am facing a problem while loading all images from device in a 'GridView', I am using 'MediaStore' to fetch images and i am quite successfull in that and also i have divided all the images folder wise
My phone is having 1 GB ram so i am able load images without difficulties,
But the problem i am facing is that when i use it another device with less then my phone's ram it takes more time to load the images and sometimes it just don't load any image i have already tried using 'AsyncTask' but its not helping.
Below is what i have done so far:
public class DirectoryImagesActivity extends Activity {
private ImageAdapter imageAdapter;
public static String[] arrPath;
private boolean[] thumbnailsselection;
private int ids[];
private int count;
Bundle dirBundle;
String dirName;
public static Bitmap[] imageThumb;
ArrayList<Bitmap> dirBitmap = new ArrayList<Bitmap>();
/**
* Overrides methods
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.photo_gallery);
dirBundle = getIntent().getExtras();
dirName = dirBundle.getString("dir_name");
String[] projectionFolder = { MediaStore.Images.Media._ID,
MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
MediaStore.Images.Media.DATA };
String selection = MediaStore.Images.Media.BUCKET_DISPLAY_NAME + " = ?";
String[] selectionArgs = new String[] { dirName };
#SuppressWarnings("deprecation")
Cursor mImageCursor = managedQuery(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projectionFolder,
selection, selectionArgs, null);
int image_column_index = mImageCursor
.getColumnIndex(MediaStore.Images.Media._ID);
this.count = mImageCursor.getCount();
arrPath = new String[this.count];
imageThumb = new Bitmap[this.count];
ids = new int[count];
this.thumbnailsselection = new boolean[this.count];
for (int i = 0; i < this.count; i++) {
mImageCursor.moveToPosition(i);
ids[i] = mImageCursor.getInt(image_column_index);
int dataColumnIndex = mImageCursor
.getColumnIndex(MediaStore.Images.Media.DATA);
arrPath[i] = mImageCursor.getString(dataColumnIndex);
int id = mImageCursor.getInt(mImageCursor
.getColumnIndex(MediaStore.MediaColumns._ID));
dirBitmap.add(MediaStore.Images.Thumbnails.getThumbnail(
getContentResolver(), id,
MediaStore.Images.Thumbnails.MICRO_KIND, null));
}
GridView imagegrid = (GridView) findViewById(R.id.PhoneImageGrid);
imageAdapter = new ImageAdapter(this);
imagegrid.setAdapter(imageAdapter);
// imagecursor.close();
final Button selectBtn = (Button) findViewById(R.id.selectBtn);
selectBtn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
final int len = thumbnailsselection.length;
int cnt = 0;
String selectImages = "";
for (int i = 0; i < len; i++) {
if (thumbnailsselection[i]) {
cnt++;
selectImages = selectImages + arrPath[i] + "|";
}
}
if (cnt == 0) {
Toast.makeText(getApplicationContext(),
"Please select at least one image",
Toast.LENGTH_LONG).show();
} else {
Log.d("SelectedImages", selectImages);
Intent i = new Intent();
i.putExtra("data", selectImages);
setResult(Activity.RESULT_OK, i);
finish();
}
}
});
}
#Override
public void onBackPressed() {
setResult(Activity.RESULT_CANCELED);
super.onBackPressed();
}
/**
* Class method
*/
/**
* This method used to set bitmap.
*
* #param iv
* represented ImageView
* #param id
* represented id
*/
public void setBitmap(final ImageView iv, final Bitmap id) {
new AsyncTask<Void, Void, Bitmap>() {
#Override
protected Bitmap doInBackground(Void... params) {
return id;
}
#Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
iv.setImageBitmap(result);
}
}.execute();
}
/**
* List adapter
*
* #author tasol
*/
public class ImageAdapter extends BaseAdapter {
private LayoutInflater mInflater;
public ImageLoader imageLoader;
Context context;
public ImageAdapter(Context context) {
this.context = context;
mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
imageLoader = new ImageLoader(context);
}
public int getCount() {
return dirBitmap.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(final int position, View convertView,
ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.layout_improved_grid,
null);
holder.imageview = (SquareImageView) convertView
.findViewById(R.id.thumbImage);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.imageview.setId(position);
// holder.imageview.setImageBitmap(imageThumb[position]);
holder.imageview.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Toast.makeText(DirectoryImagesActivity.this,
"Item Clicked", Toast.LENGTH_LONG).show();
Intent i = new Intent(getApplicationContext(),
FullImageActivity.class); // passing array index
i.putExtra("id", position);
startActivity(i);
}
});
try {
setBitmap(holder.imageview, dirBitmap.get(position));
} catch (Throwable e) {
}
holder.id = position;
return convertView;
}
}
/**
* Inner class
*
* #author tasol
*/
class ViewHolder {
SquareImageView imageview;
int id;
}
public static Bitmap convertBitmap(String path) {
Bitmap bitmap = null;
BitmapFactory.Options bfOptions = new BitmapFactory.Options();
bfOptions.inDither = false; // Disable Dithering mode
bfOptions.inPurgeable = true; // Tell to gc that whether it needs free
// memory, the Bitmap can be cleared
bfOptions.inInputShareable = true; // Which kind of reference will be
// used to recover the Bitmap data
// after being clear, when it will
// be used in the future
bfOptions.inTempStorage = new byte[32 * 1024];
File file = new File(path);
FileInputStream fs = null;
try {
fs = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
if (fs != null) {
bitmap = BitmapFactory.decodeFileDescriptor(fs.getFD(), null,
bfOptions);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fs != null) {
try {
fs.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return bitmap;
}
}
If anybody can help me with this thank you in advance
Try this is working solution
1)PhotoGalaryActivity.java
public class PhotoGalaryActivity extends Activity {
private ImageAdapter imageAdapter;
private String[] arrPath;
private boolean[] thumbnailsselection;
private int ids[];
private int count;
/**
* Overrides methods
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.photo_gallery);
final String[] columns = { MediaStore.Images.Media.DATA, MediaStore.Images.Media._ID };
final String orderBy = MediaStore.Images.Media._ID;
#SuppressWarnings("deprecation")
Cursor imagecursor = managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, null, null, orderBy);
int image_column_index = imagecursor.getColumnIndex(MediaStore.Images.Media._ID);
this.count = imagecursor.getCount();
this.arrPath = new String[this.count];
ids = new int[count];
this.thumbnailsselection = new boolean[this.count];
for (int i = 0; i < this.count; i++) {
imagecursor.moveToPosition(i);
ids[i] = imagecursor.getInt(image_column_index);
int dataColumnIndex = imagecursor.getColumnIndex(MediaStore.Images.Media.DATA);
arrPath[i] = imagecursor.getString(dataColumnIndex);
}
GridView imagegrid = (GridView) findViewById(R.id.PhoneImageGrid);
imageAdapter = new ImageAdapter();
imagegrid.setAdapter(imageAdapter);
imagecursor.close();
final Button selectBtn = (Button) findViewById(R.id.selectBtn);
selectBtn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
final int len = thumbnailsselection.length;
int cnt = 0;
String selectImages = "";
for (int i = 0; i < len; i++) {
if (thumbnailsselection[i]) {
cnt++;
selectImages = selectImages + arrPath[i] + "|";
}
}
if (cnt == 0) {
Toast.makeText(getApplicationContext(), "Please select at least one image", Toast.LENGTH_LONG).show();
} else {
Log.d("SelectedImages", selectImages);
Intent i = new Intent();
i.putExtra("data", selectImages);
setResult(Activity.RESULT_OK, i);
finish();
}
}
});
}
#Override
public void onBackPressed() {
setResult(Activity.RESULT_CANCELED);
super.onBackPressed();
}
/**
* Class method
*/
/**
* This method used to set bitmap.
* #param iv represented ImageView
* #param id represented id
*/
private void setBitmap(final ImageView iv, final int id) {
new AsyncTask<Void, Void, Bitmap>() {
#Override
protected Bitmap doInBackground(Void... params) {
return MediaStore.Images.Thumbnails.getThumbnail(getApplicationContext().getContentResolver(), id, MediaStore.Images.Thumbnails.MICRO_KIND, null);
}
#Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
iv.setImageBitmap(result);
}
}.execute();
}
/**
* List adapter
* #author tasol
*/
public class ImageAdapter extends BaseAdapter {
private LayoutInflater mInflater;
public ImageAdapter() {
mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
return count;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.photo_gallery_item, null);
holder.imageview = (ImageView) convertView.findViewById(R.id.thumbImage);
holder.checkBox = (CheckBox) convertView.findViewById(R.id.itemCheckBox);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.checkBox.setId(position);
holder.imageview.setId(position);
holder.checkBox.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
CheckBox cb = (CheckBox) v;
int id = cb.getId();
if (thumbnailsselection[id]) {
cb.setChecked(false);
thumbnailsselection[id] = false;
} else {
cb.setChecked(true);
thumbnailsselection[id] = true;
}
}
});
holder.imageview.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
int id = holder.checkBox.getId();
if (thumbnailsselection[id]) {
holder.checkBox.setChecked(false);
thumbnailsselection[id] = false;
} else {
holder.checkBox.setChecked(true);
thumbnailsselection[id] = true;
}
}
});
try {
setBitmap(holder.imageview, ids[position]);
} catch (Throwable e) {
}
holder.checkBox.setChecked(thumbnailsselection[position]);
holder.id = position;
return convertView;
}
}
/**
* Inner class
* #author tasol
*/
class ViewHolder {
ImageView imageview;
CheckBox checkBox;
int id;
}
}
2)photo_gallery.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="match_parent">
<ImageView android:id="#+id/thumbImage" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_centerInParent="true"
/>
<CheckBox android:id="#+id/itemCheckBox" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_alignParentRight="true"
android:layout_alignParentTop="true" />
</RelativeLayout>
3)photo_gallery_item.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="match_parent">
<ImageView android:id="#+id/thumbImage" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_centerInParent="true"
/>
<CheckBox android:id="#+id/itemCheckBox" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_alignParentRight="true"
android:layout_alignParentTop="true" />
</RelativeLayout>
As there are many images you are loading you have to implement lazy loading in-order to increase app's performance for other low memory devices.
You can refer this library https://github.com/nostra13/Android-Universal-Image-Loader.
I hope this helps.