A few hours ago, I asked about AUIL call too many getView(). (Universal Image Loader - call too many getView())
By answers, I solve the problem that getView() was called too many times.
However, I've still have a problem.
When the activity was started, I can see the list. However, soon after, the list view was removed (or cleared). No images appear or load on the list view.
This is my source code.
public class MainActivity extends Activity{
AsyncTask<Void, Void, Void> asyncTask, registerTask;
DisplayImageOptions options;
ArrayList<HashMap<String, Object>> feedList = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int cacheSize = ((ActivityManager)getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass() * 1024 * 1024 / 8;
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this)
.memoryCacheExtraOptions(metrics.widthPixels, metrics.heightPixels)
.diskCacheExtraOptions(metrics.widthPixels, metrics.heightPixels, null)
.memoryCache(new LruMemoryCache(cacheSize))
.memoryCacheSize(cacheSize)
.memoryCacheSizePercentage(13)
.diskCache(new UnlimitedDiscCache(StorageUtils.getCacheDirectory(this)))
.diskCacheSize(100 * 1024 * 1024)
.diskCacheFileCount(200)
.diskCacheFileNameGenerator(new HashCodeFileNameGenerator())
.imageDownloader(new BaseImageDownloader(this))
.imageDecoder(new BaseImageDecoder(false))
.defaultDisplayImageOptions(DisplayImageOptions.createSimple())
.build();
ImageLoader.getInstance().init(config);
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.ic_stub)
.showImageForEmptyUri(R.drawable.ic_empty)
.showImageOnFail(R.drawable.ic_error)
.cacheInMemory(true)
.cacheOnDisk(true)
.considerExifParams(true)
.displayer(new RoundedBitmapDisplayer(20))
.build();
asyncTask = new AsyncTask<Void, Void, Void>() {
protected Void doInBackground(Void... params) {
StyleFeedServerUtils serverUtils = new StyleFeedServerUtils();
feedList = serverUtils.getStyleFeedList(MainActivity.this);
return null;
}
#Override
protected void onPostExecute(Void result) {
if(feedList != null && feedList.size() > 0){
final ListView listView = (ListView)findViewById(R.id.list);
listView.setAdapter(new ImageAdapter());
PauseOnScrollListener listener = new PauseOnScrollListener(ImageLoader.getInstance(), true, true);
listView.setOnScrollListener(listener);
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.e("fashion", "onItemClick, position : "+position);
}
});
}
asyncTask.cancel(!isCancelled());
asyncTask = null;
}
};
asyncTask.execute(null, null, null);
}
#Override
public void onDestroy() {
super.onDestroy();
if (registerTask != null) {
registerTask.cancel(true);
}
//GCMRegistrar.onDestroy(this);
AnimateFirstDisplayListener.displayedImages.clear();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
class ImageAdapter extends BaseAdapter {
private LayoutInflater inflater;
private ImageLoadingListener animateFirstListener = new AnimateFirstDisplayListener();
ImageAdapter() {
inflater = LayoutInflater.from(MainActivity.this);
}
#Override
public int getCount() {
return feedList.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
if(convertView == null){
view = inflater.inflate(R.layout.style_feed_list_view, parent, false);
view.setTag((ImageView)view.findViewById(R.id.style_feed_image));
}
ImageLoader.getInstance().displayImage(feedList.get(position).get("URL").toString(), (ImageView)view.getTag(), options, animateFirstListener);
return view;
}
}
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);
}
}
}
}
}
Please help.
some times it create problem due to RoundedBitmapDisplayer just comment .displayer(new RoundedBitmapDisplayer(20)) this line and try to run again.
If you want to use rounded image view then try library from below
https://github.com/vinc3m1/RoundedImageView
Related
I am Using Universal Image Loader library in order to set images from the server in my recycler view.
In my recycler View when I start to scroll on it, It will setup unrelated images for a few seconds and after that, it will set true image.
I don't know where is the problem.
This is my Adapter That I'm using:
public class HistoryDetailAdapter extends RecyclerView.Adapter<HistoryDetailAdapter.ViewHolder> {
private List<PList> menuItems;
private Context mContext;
private ActivityHistoryDetails activityHistoryDetails;
private DisplayImageOptions defaultOptions;
private ImageLoaderConfiguration config;
public HistoryDetailAdapter(List<PList> menuItems, Context mContext) {
this.menuItems = menuItems;
this.mContext = mContext;
this.activityHistoryDetails = (ActivityHistoryDetails) mContext;
byte[] toEncrypt = (G.getPremiumState()[0] + ":" + G.getPremiumState()[1]).getBytes();
String encryptedCredentials = Base64.encodeToString(toEncrypt, Base64.DEFAULT);
Map<String, String> headers = new HashMap();
headers.put("Authorization", "Basic " + encryptedCredentials);
defaultOptions = new DisplayImageOptions.Builder()
.cacheInMemory(false)
.cacheOnDisk(false)
.resetViewBeforeLoading(true)
.delayBeforeLoading(5000)
.showImageOnLoading(R.drawable.loading_02)
.showImageOnFail(R.drawable.ic_empty_white_box)
.extraForDownloader(headers)
.build();
config = new ImageLoaderConfiguration.Builder(activityHistoryDetails)
.defaultDisplayImageOptions(defaultOptions)
.imageDownloader(new AuthDownloader(activityHistoryDetails))
.build();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
ImageView imgDefault;
LinearLayout parentLayout;
CoordinatorLayout coordinatorLayout;
public ViewHolder(View v) {
super(v);
imgDefault = (ImageView) v.findViewById(R.id.img_defaultImage);
parentLayout = (LinearLayout) v.findViewById(R.id.parentLayout);
coordinatorLayout = (CoordinatorLayout) v.findViewById(R.id.coordinatorLayout);
}
}
#Override
public HistoryDetailAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// Create a new View
final View v = LayoutInflater.from(activityHistoryDetails).inflate(R.layout.activity_history_detail_recycler, parent, false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
//Download and Load Default Image from server into imgDefault ImageView
String url = "http://192.168.14.77:8080/api/images/download/";
if (menuItems.get(position).getPDefaultImage().getIId() != null) {
url += menuItems.get(position).getPDefaultImage().getIId();
ImageLoader imageLoader = ImageLoader.getInstance(); // Get singleton instance
imageLoader.init(config);
imageLoader.handleSlowNetwork(true);
// Load image, decode it to Bitmap and return Bitmap to callback
ImageSize targetSize = new ImageSize(120, 120); // result Bitmap will be fit to this size
imageLoader.loadImage(url, targetSize, new SimpleImageLoadingListener() {
#Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
// Do whatever you want with Bitmap
holder.imgDefault.setImageBitmap(loadedImage);
}
});
} else {
holder.imgDefault.setImageResource(R.drawable.loading_01);
}
}
#Override
public int getItemCount() {
if (menuItems.size() > 0) {
return menuItems.size();
} else {
return 0;
}
}
public List<PList> getList() {
return menuItems;
}
}
Thank you for your answers.
You can use Glide or Fresco image library for it. They are working stable.
What I'm trying to achieve is to obtain the URL received from Instagram and pass its array position to an onlick listener for each corresponding photo in a grid view.
Here is my code:
MainActivity.java
public class MainActivity extends Activity {
private InstagramSession mInstagramSession;
private Instagram mInstagram;
private ProgressBar mLoadingPb;
private GridView mGridView;
private static final String CLIENT_ID = "83549f9eb76f4a5b90daf6e4e14da107";
private static final String CLIENT_SECRET = "6df26b0c8f664323a07126bfe8511651";
private static final String REDIRECT_URI = "http://www.yahoo.com";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mInstagram = new Instagram(this, CLIENT_ID, CLIENT_SECRET, REDIRECT_URI);
mInstagramSession = mInstagram.getSession();
if (mInstagramSession.isActive()) {
setContentView(R.layout.activity_user);
InstagramUser instagramUser = mInstagramSession.getUser();
mLoadingPb = (ProgressBar) findViewById(R.id.pb_loading);
mGridView = (GridView) findViewById(R.id.gridView);
((TextView) findViewById(R.id.tv_name)).setText(instagramUser.fullName);
((TextView) findViewById(R.id.tv_username)).setText(instagramUser.username);
((Button) findViewById(R.id.btn_logout)).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
mInstagramSession.reset();
startActivity(new Intent(MainActivity.this, MainActivity.class));
finish();
}
});
ImageView userIv = (ImageView) findViewById(R.id.iv_user);
DisplayImageOptions displayOptions = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.ic_user)
.showImageForEmptyUri(R.drawable.ic_user)
.showImageOnFail(R.drawable.ic_user)
.cacheInMemory(true)
.cacheOnDisc(false)
.considerExifParams(true)
.build();
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this)
.writeDebugLogs()
.defaultDisplayImageOptions(displayOptions)
.build();
ImageLoader imageLoader = ImageLoader.getInstance();
imageLoader.init(config);
AnimateFirstDisplayListener animate = new AnimateFirstDisplayListener();
imageLoader.displayImage(instagramUser.profilPicture, userIv, animate);
new DownloadTask().execute();
} else {
setContentView(R.layout.activity_main);
((Button) findViewById(R.id.btn_connect)).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
mInstagram.authorize(mAuthListener);
}
});
}
}
private void showToast(String text) {
Toast.makeText(getApplicationContext(), text, Toast.LENGTH_LONG).show();
}
private Instagram.InstagramAuthListener mAuthListener = new Instagram.InstagramAuthListener() {
#Override
public void onSuccess(InstagramUser user) {
finish();
startActivity(new Intent(MainActivity.this, MainActivity.class));
}
#Override
public void onError(String error) {
showToast(error);
}
#Override
public void onCancel() {
showToast("OK. Maybe later?");
}
};
public 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);
}
}
}
}
ArrayList<String> photoList;
public class DownloadTask extends AsyncTask<URL, Integer, Long> {
protected void onCancelled() {
}
protected void onPreExecute() {
}
protected Long doInBackground(URL... urls) {
long result = 0;
try {
List<NameValuePair> params = new ArrayList<NameValuePair>(1);
params.add(new BasicNameValuePair("count", "20"));
InstagramRequest request = new InstagramRequest(mInstagramSession.getAccessToken());
String response = request.createRequest("GET", "/users/21846697/media/recent", params);
if (!response.equals("")) {
JSONObject jsonObj = (JSONObject) new JSONTokener(response).nextValue();
JSONArray jsonData = jsonObj.getJSONArray("data");
int length = jsonData.length();
if (length > 0) {
photoList = new ArrayList<String>();
for (int i = 0; i < length; i++) {
JSONObject jsonPhoto = jsonData.getJSONObject(i).getJSONObject("images").getJSONObject("standard_resolution");
photoList.add(jsonPhoto.getString("url"));
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
protected void onProgressUpdate(Integer... progress) {
}
protected void onPostExecute(Long result) {
mLoadingPb.setVisibility(View.GONE);
if (photoList == null) {
Toast.makeText(getApplicationContext(), "No Photos Available", Toast.LENGTH_LONG).show();
} else {
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int width = (int) Math.ceil((double) dm.widthPixels / 2);
width=width-50;
int height = width;
PhotoListAdapter adapter = new PhotoListAdapter(MainActivity.this);
adapter.setData(photoList);
adapter.setLayoutParam(width, height);
mGridView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// Maybe you'll have to cast it to a string, I'm currently writing directly in SO
String url = (String) parent.getAdapter().getItem(position);
Intent myintent=new Intent(MainActivity.this, FullscreenImageView.class).putExtra("SelectedImageURL", position);
startActivity(myintent);
}
});
mGridView.setAdapter(adapter);
}
}
}
}
PhotoListAdapter.java
public class PhotoListAdapter extends BaseAdapter {
private Context mContext;
private ImageLoader mImageLoader;
private AnimateFirstDisplayListener mAnimator;
private ArrayList<String> mPhotoList;
private int mWidth;
private int mHeight;
public PhotoListAdapter(Context context) {
mContext = context;
DisplayImageOptions displayOptions = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.instagram_logo)
.showImageForEmptyUri(R.drawable.instagram_logo)
.showImageOnFail(R.drawable.instagram_logo)
.cacheInMemory(true)
.cacheOnDisc(false)
.considerExifParams(true)
.build();
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
.writeDebugLogs()
.defaultDisplayImageOptions(displayOptions)
.build();
mImageLoader = ImageLoader.getInstance();
mImageLoader.init(config);
mAnimator = new AnimateFirstDisplayListener();
}
public void setData(ArrayList<String> data) {
mPhotoList = data;
}
public void setLayoutParam(int width, int height) {
mWidth = width;
mHeight = height;
}
#Override
public int getCount() {
return (mPhotoList == null) ? 0 : mPhotoList.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageIv;
if (convertView == null) {
imageIv = new ImageView(mContext);
imageIv.setLayoutParams(new GridView.LayoutParams(mWidth, mHeight));
imageIv.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
imageIv.setPadding(0, 0, 0, 0);
} else {
imageIv = (ImageView) convertView;
}
mImageLoader.displayImage(mPhotoList.get(position), imageIv, mAnimator);
return imageIv;
}
}
FullScreenImageView.java
import android.app.Activity;
public class FullscreenImageView extends Activity {
String imageURL = getIntent().getStringExtra("SelectedImageURL");
}
The workflow of the gridView as you understood is to have an adapter to populate this view.
What I would do is that the getItem(int position) returns the URL which, if I good understood, is contained in your mPhotoList. Something like:
#Override
public Object getItem(int position) {
return mPhotoList.get(position);
}
And use it where you need it like this:
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// Maybe you'll have to cast it to a string, I'm currently writing directly in SO
String url = parent.getAdapter().getItem(position)
Intent myintent=new Intent(MainActivity.this, FullscreenImageView.class).putExtra("SelectedImageURL", url);
startActivity(myintent);
}
});
Hope it helps.
I have an array of references that I bring into the adapter and load them pictures.
public final class Constants {
public static final String[] IMAGES = new String[] {
"link1",
"link2",
"link3",
"link4",
"link5",
....
}
and in MyActivity...
...
static String[] imageUrls = null;
...
imageUrls = Constants.IMAGES;
...
imageLoader.displayImage(**imageUrls[position]**, holder.imageView, options, new SimpleImageLoadingListener() {...}
and everything works! but when I try to get links s Internet then there is an error...
interface IOnParseResult {void onDone(ArrayList<String> data);}
public class NewThread extends AsyncTask<String, Void, String> {
Elements title;
ArrayList<String> data;
IOnParseResult onParseResult;
#Override
protected String doInBackground(String... arg) {
Document doc;
try {
data = new ArrayList<String>();
doc = Jsoup.connect(arg[0]).get();
title = doc.select("div");
String m;
for (Element titles : title) {
if (titles.children().hasClass("btl")){
m = titles.select("img").attr("abs:src");
data.add(m);
}
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result) {
if (onParseResult == null) return;
onParseResult.onDone(data);
}
public void setOnParseResult(IOnParseResult onParseResult) {
this.onParseResult = onParseResult;
}
}
and in the output data stream can log in normally, they are loaded, but I can not transfer them to your Activity
...
static String[] imageUrls = null;
NewThread t = new NewThread();
...
t.setOnParseResult(new IOnParseResult() {
#Override
public void onDone(ArrayList<String> data) {
imageUrls = data.toArray(new String[data.size()]);
}
});
t.execute("http://www.kartinki24.ru/kartinki/3d/");
...
error log
04-05 10:43:53.973: ERROR/AndroidRuntime(1613): FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.SimpleFromEclipse/com.example.SimpleFromEclipse.ImageGridActivity}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1647)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
at android.app.ActivityThread.access$1500(ActivityThread.java:117)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:3683)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.example.SimpleFromEclipse.ImageGridActivity$ImageAdapter.getCount(ImageGridActivity.java:89)
at android.widget.GridView.setAdapter(GridView.java:131)
at com.example.SimpleFromEclipse.ImageGridActivity.onCreate(ImageGridActivity.java:70)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
... 11 more
// at com.example.SimpleFromEclipse.ImageGridActivity$ImageAdapter.getCount(ImageGridActivity.java:89)
#Override
public int getCount() {
return imageUrls.length;
}
full code
public class ImageGridActivity extends AbsListViewBaseActivity {
static String[] imageUrls = null;
DisplayImageOptions options;
NewThread t;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ac_image_grid);
imageLoader.init(ImageLoaderConfiguration.createDefault(this));
t = new NewThread();
t.setOnParseResult(new IOnParseResult() {
#Override
public void onDone(ArrayList<String> data) {
imageUrls = data.toArray(new String[data.size()]);
}
});
t.execute("http://www.kartinki24.ru/kartinki/3d/");
//Log.d("HZ", imageUrls[0]);
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.ic_stub)
.showImageForEmptyUri(R.drawable.ic_empty)
.showImageOnFail(R.drawable.ic_error)
.cacheInMemory(true)
.cacheOnDisc(true)
.considerExifParams(true)
.bitmapConfig(Bitmap.Config.RGB_565)
.build();
listView = (GridView) findViewById(R.id.gridview);
((GridView) listView).setAdapter(new ImageAdapter());
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
startImagePagerActivity(position);
}
});
}
private void startImagePagerActivity(int position) {
Intent intent = new Intent(this, ImagePagerActivity.class);
intent.putExtra(Constants.Extra.IMAGES, imageUrls);
intent.putExtra(Constants.Extra.IMAGE_POSITION, position);
startActivity(intent);
}
public class ImageAdapter extends BaseAdapter {
#Override
public int getCount() {
return imageUrls.length;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
View view = convertView;
if (view == null) {
view = getLayoutInflater().inflate(R.layout.item_grid_image, parent, false);
holder = new ViewHolder();
assert view != null;
holder.imageView = (ImageView) view.findViewById(R.id.image);
holder.progressBar = (ProgressBar) view.findViewById(R.id.progress);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
imageLoader.displayImage(imageUrls[position], holder.imageView, options, new SimpleImageLoadingListener() {
#Override
public void onLoadingStarted(String imageUri, View view) {
holder.progressBar.setProgress(0);
holder.progressBar.setVisibility(View.VISIBLE);
}
#Override
public void onLoadingFailed(String imageUri, View view,
FailReason failReason) {
holder.progressBar.setVisibility(View.GONE);
}
#Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
holder.progressBar.setVisibility(View.GONE);
}
}, new ImageLoadingProgressListener() {
#Override
public void onProgressUpdate(String imageUri, View view, int current,
int total) {
holder.progressBar.setProgress(Math.round(100.0f * current / total));
}
}
);
return view;
}
class ViewHolder {
ImageView imageView;
ProgressBar progressBar;
}
}
}
From where is the getCount() called exactly? Because if your code is like this
t.setOnParseResult(new IOnParseResult() {
#Override
public void onDone(ArrayList<String> data) {
imageUrls = data.toArray(new String[data.size()]);
}
});
t.execute("..");
SomeFunctionThatCausesCallOfGetCount();
it will crash. You need it to be
t.setOnParseResult(new IOnParseResult() {
#Override
public void onDone(ArrayList<String> data) {
imageUrls = data.toArray(new String[data.size()]);
SomeFunctionThatCausesCallOfGetCount();
}
});
t.execute(...);
You are probably calling the setAdapter() outside the onDone callback. You need to put it inside the callback.
Update:
Change your onCreate like this
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ac_image_grid);
imageLoader.init(ImageLoaderConfiguration.createDefault(this));
t = new NewThread();
t.setOnParseResult(new IOnParseResult() {
#Override
public void onDone(ArrayList<String> data) {
imageUrls = data.toArray(new String[data.size()]);
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.ic_stub)
.showImageForEmptyUri(R.drawable.ic_empty)
.showImageOnFail(R.drawable.ic_error)
.cacheInMemory(true)
.cacheOnDisc(true)
.considerExifParams(true)
.bitmapConfig(Bitmap.Config.RGB_565)
.build();
listView = (GridView) findViewById(R.id.gridview);
((GridView) listView).setAdapter(new ImageAdapter());
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
startImagePagerActivity(position);
}
});
}
});
t.execute("http://www.kartinki24.ru/kartinki/3d/");
}
I've done XML parsing to ListView and right now do i need to implement load-more feature. I know how to indicat, when the user scrolled to the bottom and how to limit the number of items in a ListView. But is there any way how to show more items when the user scrolls to the end of the list?
Here is my adapter class:
public class ClubsAdapter extends ArrayAdapter<LeagueClub> {
ImageLoader imageLoader;
DisplayImageOptions options;
Context mContext;
public static List<LeagueClub> mClubs;
#SuppressWarnings("deprecation")
public ClubsAdapter(Context mContext, int textViewResourceId, List<LeagueClub> clubs) {
super(mContext, textViewResourceId, clubs);
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(mContext).build();
imageLoader = ImageLoader.getInstance();
imageLoader.init(config);
options = new DisplayImageOptions.Builder()
.cacheInMemory()
.cacheOnDisc()
.build();
mClubs=clubs;
}
#Override
public View getView(int pos, View convertView, ViewGroup parent){
RelativeLayout row = (RelativeLayout)convertView;
Log.i("PremierLeague", "getView pos = " + pos);
if(null == row){
LayoutInflater inflater = (LayoutInflater)parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = (RelativeLayout)inflater.inflate(R.layout.row_site, null);
}
final ImageView clubLogo = (ImageView)row.findViewById(R.id.clubLogo);
TextView nameTxt = (TextView)row.findViewById(R.id.nameTxt);
TextView aboutTxt = (TextView)row.findViewById(R.id.aboutTxt);
TextView stadiumTxt = (TextView)row.findViewById(R.id.stadiumTxt);
final ProgressBar indicator = (ProgressBar)row.findViewById(R.id.progress);
indicator.setVisibility(View.VISIBLE);
clubLogo.setVisibility(View.INVISIBLE);
ImageLoadingListener listener = new ImageLoadingListener(){
#Override
public void onLoadingStarted(String arg0, View arg1) {
// TODO Auto-generated method stub
}
#Override
public void onLoadingCancelled(String arg0, View arg1) {
// TODO Auto-generated method stub
}
#Override
public void onLoadingComplete(String arg0, View arg1, Bitmap arg2) {
indicator.setVisibility(View.INVISIBLE);
clubLogo.setVisibility(View.VISIBLE);
}
#Override
public void onLoadingFailed(String arg0, View view, FailReason arg2) {
indicator.setVisibility(View.INVISIBLE);
ImageView imageView = (ImageView) view.findViewById(R.id.clubLogo);
imageView.setVisibility(View.VISIBLE);
}
};
imageLoader.displayImage(getItem(pos).getLogo(), clubLogo,options, listener);
nameTxt.setText(getItem(pos).getName());
aboutTxt.setText(getItem(pos).getAbout());
stadiumTxt.setText(getItem(pos).getStadium());
return row;
}
public int getCount() {
return mClubs.size(); //If i set return 10; it limits items to max 10
}
}
And here is my Fragment:
public class Fragment2 extends Fragment {
static PullToRefreshListView mListView;
static ClubsAdapter mAdapter;
Context mContext;
ProgressBar mProgress;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_2, container, false);
mListView = (PullToRefreshListView) rootView.findViewById(R.id.pull_to_refresh_listview1);
mProgress = (ProgressBar) rootView.findViewById(R.id.loading_clubs);
mProgress.setVisibility(View.VISIBLE);
ClubsDownloadTask task = new ClubsDownloadTask();
task.execute();
mListView.setOnRefreshListener(new OnRefreshListener<ListView>() {
#Override
public void onRefresh(PullToRefreshBase<ListView> refreshView) {
// Do work to refresh the list here.
mProgress.setVisibility(View.INVISIBLE);
ClubsDownloadTask task = new ClubsDownloadTask();
task.execute();
}
});
return rootView;
}
private class ClubsDownloadTask extends AsyncTask<Void, Void, Void>{
private ClubsAdapter mAdapter;
#Override
protected Void doInBackground(Void... arg0) {
try {
Downloader.DownloadFromUrl("http://dl.dropboxusercontent.com/s/h2qc41k2yy3c1ir/clubs.xml", getActivity().openFileOutput("clubs.xml", Context.MODE_PRIVATE));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}
protected void onPreExecute() {
}
protected void onPostExecute(Void result){
mListView.onRefreshComplete();
mProgress.setVisibility(View.INVISIBLE);
mAdapter = new ClubsAdapter(getActivity(), -1 , ClubsXmlPullParser.getItemsFromFile(getActivity()));
mListView.setAdapter(mAdapter);
if(ClubsAdapter.mClubs != null){
mAdapter.clear();
for (int i = 0; i < ClubsAdapter.mClubs.size(); i++) {
mAdapter.add(ClubsAdapter.mClubs.get(i));
}
mListView.setOnScrollListener(new OnScrollListener() {
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
int totalItemCount) {
if(mListView.getRefreshableView().getCount()!=0&&mListView.getRefreshableView().getCount()>0&&mAdapter.getCount()!=0){
if (mListView.getRefreshableView().getLastVisiblePosition() == mListView.getRefreshableView().getAdapter().getCount() - 1
&& mListView.getRefreshableView()
.getChildAt(mListView.getRefreshableView().getChildCount() - 1)
.getBottom() <= mListView.getRefreshableView().getHeight()) {
//Here do I need to load more items
}
}
}
#Override
public void onScrollStateChanged(AbsListView view,
int scrollState) {
if (SCROLL_STATE_TOUCH_SCROLL == scrollState) {
View currentFocus = getActivity().getCurrentFocus();
if(currentFocus != null) {
currentFocus.clearFocus();
}
}
}
});
}
}
}
}
Thanks for any suggestion!
You can use this adapter https://github.com/commonsguy/cwac-endless
With this adapter, when user scroll to end of list, it will call a function which you can implement to load more items.
Hello stackoverflow I'm trying to develop an application like Gallery for a particular directory of SD Card. For example I have took WhatsApp Images directory, here is my code
public class WhatsAppInboxImagesActivity extends Activity {
private ImageAdapter imageAdapter;
private ProgressDialog pd;
ArrayList<String> f = null;
File[] listFile;
Button btnDelete;
HashSet<String> selectedFile = null;
GridView imagegrid;
AlertDialog alertDialog = null;
static
{
File noFile = new File(Environment.getExternalStorageDirectory().getPath(), "/WhatsApp/Media/WhatsApp Images/Sent/.nomedia");
if(noFile.exists())
{
noFile.delete();
}
}//End of static block
private void initialize()
{
imagegrid = (GridView) findViewById(R.id.PhoneImageGrid);
btnDelete = (Button) findViewById(R.id.btnDeleteImg);
selectedFile = new HashSet<String>();// list of file paths boolean checked
f = new ArrayList<String>();// list of file paths
}//End of initialize method
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_whats_app_images_inbox);
this.initialize();
getFromSdcard();
imageAdapter = new ImageAdapter();
/*
* Performing time consuming actions
*/
new AsyncTask<Void, Void, Void>()
{
#Override
protected void onPreExecute()
{
pd = ProgressDialog.show(WhatsAppInboxImagesActivity.this,
"Loading..", "Please Wait", true, false);
}// End of onPreExecute method
#Override
protected Void doInBackground(Void... params)
{
return null;
}// End of doInBackground method
#Override
protected void onPostExecute(Void result)
{
imagegrid.setAdapter(imageAdapter);
imageAdapter.notifyDataSetChanged();
pd.dismiss();
}
}.execute((Void[]) null);
btnDelete.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
new AsyncTask<Void, Void, Void>()
{
#Override
protected void onPreExecute()
{
pd = ProgressDialog.show(WhatsAppInboxImagesActivity.this,
"Loading..", "Please Wait", true, false);
}// End of onPreExecute method
#Override
protected Void doInBackground(Void... params)
{
#SuppressWarnings("rawtypes")
Iterator iterator = selectedFile.iterator();
while (iterator.hasNext())
{
new File(iterator.next().toString()).delete();
}//End of while loop
return null;
}// End of doInBackground method
#Override
protected void onPostExecute(Void result)
{
pd.dismiss();
}//End of onPostExecute method
}.execute((Void[]) null);
finish();
startActivity(getIntent());
}//End of onClick method
});//End of btnDelete anonymous class
}//End of onCreate method
public void getFromSdcard()
{
File file = new File( Environment.getExternalStorageDirectory().getPath(), "/WhatsApp/Media/WhatsApp Images");
if (file.isDirectory())
{
listFile = file.listFiles();
for (int i = 0; i < listFile.length; i++)
{
if(listFile[i].isDirectory())
{
continue;
}
f.add(listFile[i].getAbsolutePath());
}//End of for loop
}//End of if condition
}//End of getFromSdcard method
public class ImageAdapter extends BaseAdapter
{
private LayoutInflater mInflater;
public ImageAdapter()
{
mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}//End of ImageAdapter constructor
public int getCount()
{
return f.size();
}//End of getCount method
public Object getItem(int position)
{
return position;
}//End of getItem method
public long getItemId(int position)
{
return position;
}//End of getItemId method
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder;
if (convertView == null)
{
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.galleryitem, null);
holder.imageview = (ImageView) convertView.findViewById(R.id.thumbImage);
holder.checkbox = (CheckBox) convertView.findViewById(R.id.itemCheckBox);
convertView.setTag(holder);
}//End of if condition
else
{
holder = (ViewHolder) convertView.getTag();
}//End of else
BitmapFactory.Options options = new BitmapFactory.Options();
// will results in a much smaller image than the original
options.inSampleSize = 4;
// don't ever use a path to /sdcard like this, but I'm sure you have a sane way to do that
// in this case nebulae.jpg is a 19MB 8000x3874px image
final Bitmap b = BitmapFactory.decodeFile(f.get(position), options);
holder.imageview.setImageBitmap(b);
return convertView;
}//End of getView method
}//End of ImageAdapter instance inner class
class ViewHolder
{
ImageView imageview;
CheckBox checkbox;
int id;
}//End of ViewHolder instance inner class
}//End of WhatsAppImagesActivity
So far every thing is good, but the problem is images gets loaded all at one shot, so scrolling is very slow and some times OutOfMemoryException occurs though decoded file with BitMapFactory, can any one help me to solve this puzzle please.
Edit:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
if (convertView == null) {
LayoutInflater inflator = context.getLayoutInflater();
view = inflator.inflate(R.layout.list_layout, null);
final ViewHolder viewHolder = new ViewHolder();
viewHolder.text = (TextView) view.findViewById(R.id.label);
viewHolder.text.setTextColor(Color.BLACK);
viewHolder.image = (ImageView) view.findViewById(R.id.image);
viewHolder.image.setVisibility(View.GONE);
viewHolder.cb = (CheckBox) view.findViewById(R.id.item_check_box);
viewHolder.pb = (ProgressBar) view.findViewById(R.id.progressBar);
view.setTag(viewHolder);
} else {
view = convertView;
}
final int pos = position;
ViewHolder holder = (ViewHolder) view.getTag();
holder.text.setText(list.get(position).getName());
holder.image.setTag(list.get(position).getURL());
holder.image.setId(position);
PbAndImage pb_and_image = new PbAndImage();
pb_and_image.setImg(holder.image);
pb_and_image.setPb(holder.pb);
new DownloadImageTask().execute(pb_and_image);
return view;
}
Thanks.
You should use Lazy loading
visit this tutorial for lazy loading here Its very easy.
Let me know if you have any issue on it.
Edit
public class MainActivity extends ListActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String path = Environment.getExternalStorageDirectory()+"/WhatsApp/Media/WhatsApp Images";
final List<Model> list = new ArrayList<Model>();
final File file = new File(path);
final ProgressDialog dialog = ProgressDialog.show(MainActivity.this, "",
"Please Wait...", true);
new Thread(new Runnable() {
public void run() {
dismissDialog(dialog);
for(File fileChild : file.listFiles()){
list.add(get(fileChild.getName(), fileChild.getAbsolutePath()));
}
}
}).start();
ArrayAdapter<Model> adapter = new MyCustomArrayAdapter(this, list);
setListAdapter(adapter);
}
public void dismissDialog(final ProgressDialog dialog) {
runOnUiThread(new Runnable() {
public void run() {
dialog.dismiss();
}
});
}
private Model get(String s, String url) {
return new Model(s, url);
}
}
This could help: UniversalImageLoader
And that's what I did:
/**
* UniversalImageLoader載入遠端圖片,僅使用RAM做圖片快取 (Load pic & use RAM as cache)
* #param android.content.Context
* #author https://github.com/nostra13/Android-Universal-Image-Loader
* #param android.widget.ImageView - 顯示圖片的元件 (your image container)
* #param int - 載入失敗的預設圖片Resource ID (default pic if load fail, I put default pic in resources folder)
* #param java.lang.String - 檔案URL (pic URL or path)
*/
public static void imageLoaderMemoryCache(Context context, final ImageView img, final int failImgID, String url)
{
ImageLoader imageLoader=ImageLoader.getInstance();
ImageLoaderConfiguration config=new ImageLoaderConfiguration.Builder(context)
.memoryCacheExtraOptions(100, 100) // max width, max height
.threadPoolSize(5)
.threadPriority(Thread.NORM_PRIORITY+1)
.denyCacheImageMultipleSizesInMemory()
.tasksProcessingOrder(QueueProcessingType.FIFO)
.defaultDisplayImageOptions(DisplayImageOptions.createSimple())
.enableLogging()
.build();
imageLoader.init(config);
DisplayImageOptions options = new DisplayImageOptions.Builder()
.showImageForEmptyUri(R.drawable.cover_sample)
.cacheInMemory(true)
.imageScaleType(ImageScaleType.IN_SAMPLE_INT)
.bitmapConfig(Bitmap.Config.RGB_565)
.delayBeforeLoading(1)
.displayer(new FadeInBitmapDisplayer(500))
.build();
imageLoader.displayImage(url, img, options, new ImageLoadingListener()
{
#Override
public void onLoadingStarted(String url, View view)
{img.setImageResource(failImgID);} //一開始先顯示預設圖 (display default pic at first)
#Override
public void onLoadingFailed(String url, View view, FailReason failReason)
{img.setImageResource(failImgID);}
#Override
public void onLoadingComplete(String url, View view, Bitmap loadedImage)
{}
#Override
public void onLoadingCancelled(String url, View view)
{}
});
}
Usage (ListView)
public View getView(...)
{
vh.imgCover=(ImageView)convertView.findViewById(R.id.imgCover);
//...
// some stuff
//...
Util.imageLoaderDiskCache(getActivity(), vh.imgCover, R.drawable.cover_sample, "(pic file path)");
}
Hope it helps~