Suggestions to improve Activity Performance? - android

friends,
i am using following global variables in my activity
private String Session_ID;
private String uid;
// menu item starts
private final int Trash = 0x003;
private final int More = 0x005;
private final int SignOut = 0x006;
private final int SignIn = 0x007;
//menu item ends
private EfficientAdapter adap;
private String[] Msg_id;
private String[] Msg_body;
private String[] Sent_by;
private String[] Sent_on;
private String[] Is_my_message;
private String[] Photo_thumbnail;
private String[] Photo_full_path;
private String Conversation_id;
ProgressBar progressBar;
Button getMoreButton;
boolean callComplete = false;
private Handler mHandler = new Handler();
private int PageSize = Constants.pageSizeForMessages;
Object serviceData = null;
private String ConversationName;
private Uri selectedImage;
public class EfficientAdapter extends BaseAdapter implements Filterable {
private LayoutInflater mInflater;
private Context context;
public EfficientAdapter(Context context) {
mInflater = LayoutInflater.from(context);
this.context = context;
}
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
convertView = mInflater.inflate(R.layout.adaptor_contentmessagedetail, null);
holder = new ViewHolder();
holder.ImgPhoto = (ImageView)convertView.findViewById(R.id.ImgPhoto);
holder.lblMsgSentBy = (TextView) convertView.findViewById(R.id.lblSentBy);
holder.lblMsgBody = (TextView) convertView.findViewById(R.id.lblMessageBody);
holder.lblMsgSentOn = (TextView) convertView.findViewById(R.id.lblSentOn);
convertView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (!((MessageDetail)v.getContext()).isConnected()) {
Constants.DisplayMessage(v.getContext(),
Constants.CONNECTION_ERROR_MESSAGE);
return;
}
if(!Photo_full_path[position].equals(""))
{
String str= Photo_full_path[position].substring(Photo_full_path[position].length() - 3);
if(str.equals("pdf"))
{
}else
{
Intent myIntent = new Intent(v.getContext(), ViewSingleImage.class);
Bundle b = new Bundle();
b.putString("single_image_path", Photo_full_path[position] );
myIntent.putExtras(b);
v.getContext().startActivity(myIntent);
}
}
}
});
convertView.setTag(holder);
// Bind the data efficiently with the holder.
if(Is_my_message[position].equals("1"))
holder.lblMsgSentBy.setTextColor(Color.BLACK);
else
holder.lblMsgSentBy.setTextColor(Color.rgb(255, 107, 1));
SimpleDateFormat fromUser = new SimpleDateFormat(Constants.SERVICE_DATE_FORMAT);
java.text.DateFormat df=new SimpleDateFormat(Constants.DATE_FORMAT);
Date dt=new Date();
try
{
dt = fromUser.parse(Sent_on[position]);
} catch (java.text.ParseException e) {
e.printStackTrace();
}
// display photo
if(!Photo_thumbnail[position].equals(""))
{
// resize it
holder.ImgPhoto.setImageBitmap(DisplayLiveImage(Photo_thumbnail[position]));
}else
{
holder.ImgPhoto.setVisibility(View.GONE);
}
// display photo
holder.lblMsgSentBy.setText(Constants.GetSpecialCharacters(Sent_by[position]));
holder.lblMsgBody.setText(Constants.GetSpecialCharacters(Msg_body[position]));
holder.lblMsgSentOn.setText(df.format(dt));
return convertView;
}
class ViewHolder {
ImageView ImgPhoto;
TextView lblMsgSentBy;
TextView lblMsgBody;
TextView lblMsgSentOn;
}
#Override
public Filter getFilter() {
// TODO Auto-generated method stub
return null;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return Msg_id.length;
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return Msg_id[position];
}
}
public Bitmap DisplayLiveImage(String ImageSrc)
{
Bitmap bm;
try {
URL aURL = new URL(ImageSrc);
URLConnection conn = aURL.openConnection();
conn.connect();
InputStream is = null;
try
{
is= conn.getInputStream();
}catch(IOException e)
{
return null;
}
BufferedInputStream bis = new BufferedInputStream(is);
bm = BitmapFactory.decodeStream(bis);
bis.close();
is.close();
} catch (IOException e) {
return null;
}
return bm;
}
i have made them global in activity because i need them all in more than 1 functions
now my question is how to improve performance of my activity it is too slow
should i make them static or what?
any help would be appreciated.

Your global variables are almost certainly not the cause of your poor performance. Unless you're accessing them a million times, it must be something else. If you tell us what exactly is performing slower than you would expect and post the relevant code, we might be able to help.
You have a LOT of code in your getView() method. this method gets called every single time a new view gets displayed. So when the listview is created, it's called N times where N being the number of list elements that are seen. Then when you scroll, every time a new element comes onto the screen, getView() gets called again. Even if you then scroll back up, it calls getView() again.
You need to refactor your code that doesn't need to be run every time a view is created out of the view.

it is recommended to cache images and dont bring them all again and again from internet.
so my case while using custom adapter and scrolling it was again and again loading images from internet
which was causing poor performance.
and memory leakage problem too.
so what i did i followed following tutorial to load live images and my problem resolved
Answer: LazyList
http://mobilebitworks.wordpress.com/2010/11/05/android-listview-and-dynamically-loading-images-from-the-web

Related

The images in my listview changes when I scroll

This is my code:
public class GetAllCategoriesListViewAdapter extends BaseAdapter{
private JSONArray dataArray;
private Activity activity;
private static final String baseUrlForCategoryImage = "link here";
private static LayoutInflater inflater = null;
public GetAllCategoriesListViewAdapter(JSONArray jsonArray, Activity a){
this.dataArray = jsonArray;
this.activity = a;
inflater = (LayoutInflater) this.activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return this.dataArray.length();
}
#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) {
final ListCell cell;
if(convertView == null){
convertView = inflater.inflate(R.layout.get_all_categories_list_view_cell, null);
cell = new ListCell();
cell.category_name = (TextView) convertView.findViewById(R.id.category_name);
cell.category_image = (ImageView) convertView.findViewById(R.id.category_image);
cell.category_image.setTag(cell);
convertView.setTag(cell);
}else{
cell = (ListCell) convertView.getTag();
}
try{
JSONObject jsonObject = this.dataArray.getJSONObject(position);
cell.category_name.setText(jsonObject.getString("category_name"));
String nameOfImage = jsonObject.getString("category_image");
String urlForImageInServer = baseUrlForCategoryImage + nameOfImage;
new AsyncTask<String, Void, Bitmap>(){
protected Bitmap doInBackground(String... params){
String url = params[0];
Bitmap icon = null;
try{
InputStream in = new java.net.URL(url).openStream();
icon = BitmapFactory.decodeStream(in);
}catch (MalformedURLException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}
return icon;
}
#Override
protected void onPostExecute(Bitmap result) {
cell.category_image.setImageBitmap(result);
}
}.execute(urlForImageInServer);
}catch (JSONException e){
e.printStackTrace();
}
return convertView;
}
private class ListCell{
private ImageView category_image;
private TextView category_name;
}
}
The code gets the images from my webhost and place it in every cell in my listvew. The problem is everytime I scroll, the images are shuffled and returns in few seconds. How to stop the images from changing when I scroll? I tried to use the solution on other post but it won't work. Please help.
Looks like you are new to android. So you are fetching the images in the getView method. The getView method is called every time a new list item is drawn. So For every image, a new request is made to internet. SO that will be a lot of requests . You should firstly get your images and get them in some ArryayList . Then pass that Arraylist to your adapter. Here is tutorial for you
Using AsyncTask
http://www.devexchanges.info/2015/04/android-custom-listview-with-image-and.html
Using Volley
https://www.androidhive.info/2014/07/android-custom-listview-with-image-and-text-using-volley/
Go for Volley for better performance. Cheers!

ListItems doubles in number(duplicated) in Custom ListView in android

I am using a custom ListView which gets doubled in number(duplicate listItems) when I go to previous activity and again come to that ListViewActivity.
I can see where the problem occurs. When I go to the ListViewActivity for the first time everything is fine where the listitems are added to the ArrayList and the adapter is set. But when I go to the previous activity and come again to the ListViewActivity, the previously set listitems are still present in the Adapter and again the listitems are set when the process goes through setAdapter() which is causing the duplication of listitems.
I have came across many solutions like using notifyDataSetChanged(), clearing the ArrayList, setAdapter(null), etc. None of these solutions helped me.
I guess the solution is clearing the Adapterand the ArrayList and refreshing the Adapter. But I don't know how and where exactly to do it.
Here is my code:
This is the data recieving class in the LoadingActivity.java
private class CategoriesAsyncTask extends AsyncTask<String,Integer,Double>{
String res="";
String curState ="";
String httppoststr="";
boolean isNxtActivity=false;
#Override
protected Double doInBackground(String... params) {
// TODO Auto-generated method stub
postData(params[0]);
return null;
}
protected void onPostExecute(Double Result)
{
if(isNxtActivity)
{
Intent intent = new Intent(LoadingActivity.this, ListItemsActivity.class);
if(curState.equals(Constants.STATE_GET_STOCK_ITEMS))
{
intent.putStringArrayListExtra(Constants.STOCK_ITEMS_LIST, listOfItems);
intent.putExtra("curState", Constants.STATE_GET_STOCK_ITEMS);
intent.putExtra(Constants.CATEGORY_ID, categoryId);
intent.putExtra(Constants.CUSTOMER_ID, customerId);
LoadingActivity.this.startActivity(intent);
}
}
}
public void postData(String ValueIWantToSend) {
// Create a new HttpClient and Post Header
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(Constants.GatewayUrl);
try
{
JSONObject json = new JSONObject(ValueIWantToSend);
curState = json.getString("curState");
StringEntity se = new StringEntity(ValueIWantToSend);
httppost.setEntity(se);
httppost.setHeader("Accept", "application/json");
httppost.setHeader("Content-type", "application/json");
httppoststr =httppost.toString();
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
res = EntityUtils.toString(entity, "UTF-8");
JSONObject jsonobj = new JSONObject(res);
String state = jsonobj.getString(Constants.STATE);
if(Constants.RESPONSE_SUCCESS.equals(state.toLowerCase()))
{
isNxtActivity =true;
if(curState.equals(Constants.STATE_GET_STOCK_ITEMS))
{
JSONArray itemsListJsonArray=new JSONArray();
itemsListJsonArray=jsonobj.getJSONArray(Constants.STOCK_ITEMS_LIST);
for(int i=0;i<itemsListJsonArray.length();i++)
{
String itemslist=itemsListJsonArray.getString(i);
listOfItems.add(itemslist.toString());
}
}
}
}
catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
catch (JSONException e) {
e.printStackTrace();
}
}
}
ListViewActivity.java
private String[] arrayOfNames;
private String[] arrayOfImageUrls;
ArrayList<String> listOfNames = new ArrayList<String>();
ArrayList<String> listOfImageUrls = new ArrayList<String>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_items);
itemsList=(ListView) findViewById(R.id.itemsList);
Bundle extras = getIntent().getExtras();
listOfItems = extras.getStringArrayList(Constants.STOCK_ITEMS_LIST); //The duplication occurs here while getting the data from the LoadingActivity when visiting this activity for the second time.
arrayOfNames = new String[listOfNames.size()];
for(int i=0;i<listOfNames.size();i++)
{
arrayOfNames[i]=listOfNames.get(i);
}
arrayOfImageUrls = new String[listOfImageUrls.size()];
for(int i=0;i<listOfImageUrls.size();i++)
{
arrayOfImageUrls[i]=listOfImageUrls.get(i);
}
listItemadapter = new CustomListItemsAdapter(this, arrayOfNames, arrayOfImageUrls);
itemsList.setAdapter(listItemadapter);
}
CustomAdapter.java
public class CustomListItemsAdapter extends BaseAdapter{
private Context context;
private LayoutInflater inflater;
private String[] arrayOfNames;
public CustomListItemsAdapter(ListItemsActivity listItemsActivity, String[] itemsName) {
// TODO Auto-generated constructor stub
context=listItemsActivity;
arrayOfNames = itemsName;
inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return arrayOfNames.length;
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public static class ViewHolder
{
private TextView itemName;
private ImageView itemImage;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView==null)
{
holder=new ViewHolder();
convertView = inflater.inflate(R.layout.list_item_content, parent, false);
holder.itemName = (TextView) convertView.findViewById(R.id.itemName);
holder.itemImage = (ImageView) convertView.findViewById(R.id.itemImage);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.itemName.setText(arrayOfNames[position]);
StrictMode.ThreadPolicy policy = new
StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
ListItemsAsyncTask listAsync = new ListItemsAsyncTask();
Drawable drawableIcon = listAsync.loadImageFromServer(arrayOfImageUrls[position]);
holder.itemImage.setImageDrawable(drawableIcon);
return convertView;
}
private class ListItemsAsyncTask extends AsyncTask<String, Integer, Double> {
String httpPostStr, res;
Boolean NextActivity = false;
public Drawable loadImageFromServer(String url)
{
try {
InputStream is = (InputStream) new URL(url).getContent();
Drawable drawable = Drawable.createFromStream(is, "src name");
return drawable;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
#Override
protected Double doInBackground(String... params) {
return null;
}
}
Any Suggestions???
UPDATE: I have found the problem behind this duplication. The second time when I come to the ListViewActivity the duplication occurs in the Bundle from which I get the data for the ListView and its contents.
Now I need a solution to stop the duplication in the Bundle. I have mentioned the duplication occuring line with a comment in ListViewActivity.java
Call the function setAdapter() only once in onCreate() , because onCreate() is called only when the activity first starts , second time when you start the activity onCreate() is not called , but if you destroy the activity , then onCreate() will be called again , make sure you are not destroying the activity .
probably you are loading list in onResume and you are adding items to list attached to adapter and here you have duplicate each time.
Proper way is:
load data in onResume, make sure you are not adding duplicates to list, or clear list before adding data. then after fill list - check if adapter was initialised and attached if already initialised then add data to list and simple make on adapter .notifyDataSetChanged() if not initialised then initialise it with attaching your list to it.
Make attention when you attached list to adapter then you cannot change pointer to your list variable:
yourList = downloadedList; // Wrong way you will override the pointer to list in adapter
must be something like:
yourList.clear();
yourList.addAll(downloadedList); // Correct way
adapter.notifyDataSetChanged();

ListView disappears after reloading it again

I have 3 arraylist that i have combined to show in listview. Wehen i click on to generate listview, it works fine the first time but when i hit back and then click the button again, the listview shows nothing. Not sure what is cause it. I checked other post but couldnt find an answer. I am not too good with Arraylist so any details would be greatly appreciated.
I have also noticed this message in Log cat. not sure what it means.
onVisibilityChanged() is called, visibility : 0
public class Edit extends Activity implements OnItemClickListener {
private int pic;
public String filename ="User Info";
//Declaring SHareddPreference as userprofile
static SharedPreferences userprofile;
ListView listView;
List<RowItem> rowItems;
// String[] titles, descriptions;
File imgpath=null;
Context context=this;
CustomListAdapter adapter;
private List<String> Titles = new ArrayList<String>();
private List<String> Actions = new ArrayList<String>();
private List<Bitmap> Images = new ArrayList<Bitmap>();
int x;
int y=1;
int z=1;
static int a=1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.aname);
listView = (ListView)findViewById(R.id.listing);
userprofile = getSharedPreferences(filename,0);
Intent pdf=getIntent();
pic= userprofile.getInt("lastpic",pic);
x=pic;
Log.d("editpic",new Integer(pic).toString());
while(y!=x){
String comment = commentresult();
Titles.add(comment);
y++;
Log.d("y",new Integer(y).toString());
}
while(z!=x){
String act = actionresult();
Actions.add(act);
z++;
Log.d("z",new Integer(z).toString());}
while(a!=x){
Bitmap photo = getbitmap();
Images.add(photo);
a++;
Log.d("a",new Integer(a).toString());}
Titles.toArray();
Actions.toArray();
Images.toArray();
rowItems = new ArrayList<RowItem>();
for (int i = 0; i < Images.size(); i++) {
RowItem item = new RowItem(Images.get(i), Titles.get(i),Actions.get(i));
rowItems.add(item);
}
Log.d("TAG", "listview null? " + (listView == null));
CustomListAdapter adapter = new CustomListAdapter(this,
R.layout.aname_list_item, rowItems);
Log.d("TAG", "adapter=null? " + (adapter == null));
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
listView.setOnItemClickListener(this);
}
public static Bitmap getbitmap() {
String photo1 =userprofile.getString("picpath"+a, "");
File imgpath=new File(photo1);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
Bitmap bmp=DecodeImage.decodeFile(imgpath, 800, 1000, true);
bmp.compress(Bitmap.CompressFormat.JPEG, 100 , stream);
Bitmap photo2=bmp;
return photo2;
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
Toast toast = Toast.makeText(getApplicationContext(),
"Item " + (position + 1) + ": " + rowItems.get(position),
Toast.LENGTH_SHORT);
toast.setGravity(Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL, 0, 0);
toast.show();
}
public String commentresult()
{
// String com2 = null;
// while(y!=x){
String comment=userprofile.getString("comment"+y, "");
String com1=comment;
String com2=com1;
// }
return com2;
}
public String actionresult()
{
// String act2 = null;
// while(y!=x){
String action=userprofile.getString("action"+z, "");
String act1=action;
String act2=act1;
// }
return act2;
}
private static final long delay = 2000L;
private boolean mRecentlyBackPressed = false;
private Handler mExitHandler = new Handler();
private Runnable mExitRunnable = new Runnable() {
#Override
public void run() {
mRecentlyBackPressed=false;
}
};
#Override
public void onBackPressed() {
//You may also add condition if (doubleBackToExitPressedOnce || fragmentManager.getBackStackEntryCount() != 0) // in case of Fragment-based add
if (mRecentlyBackPressed) {
mExitHandler.removeCallbacks(mExitRunnable);
mExitHandler = null;
super.onBackPressed();
}
else
{
mRecentlyBackPressed = true;
Toast.makeText(this, "press again to exit", Toast.LENGTH_SHORT).show();
mExitHandler.postDelayed(mExitRunnable, delay);
}
}
#Override
public void onDestroy() {
// Destroy the AdView.
super.onDestroy();
}
Custom List Adapter:
public class CustomListAdapter extends ArrayAdapter<RowItem> {
Context context;
List<RowItem> items;
public CustomListAdapter(Context context, int resourceId,
List<RowItem> items) {
super(context, resourceId, items);
this.context = context;
this.items = items;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return items.size();
}
#Override
public RowItem getItem(int position) {
// TODO Auto-generated method stub
return items.get(position);
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
/*private view holder class*/
private class ViewHolder {
ImageView imageView;
TextView txtTitle;
TextView txtDesc;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
RowItem rowItem = getItem(position);
LayoutInflater mInflater = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.aname_list_item, null);
holder = new ViewHolder();
holder.txtDesc = (TextView) convertView.findViewById(R.id.desc);
holder.txtTitle = (TextView) convertView.findViewById(R.id.rab);
holder.imageView = (ImageView) convertView.findViewById(R.id.icon);
convertView.setTag(holder);
} else
holder = (ViewHolder) convertView.getTag();
// String name=items.get(position).getDesc();
holder.txtDesc.setText(rowItem.getDesc());
holder.txtTitle.setText(rowItem.getTitle());
holder.imageView.setImageBitmap(rowItem.getImageId());
// holder.imageView.setImageResource(Images.get(position) .getPlaceholderleft());
return convertView;
}
}
It looks like this is because you've made your variables x, y, z and a all static, which means there is a single instance of the variables shared by all instances of the class. Therefore, when you call onCreate the second time, all your while loop termination conditions are already met, so the while loops never execute. It's unclear to me why you've made these static, so unless you need them to be, you should remove the static keyword for these variables.
Why are you creating another object of ListView in onCreate() and onResume()
Remove code from onResume()
Also replace this line in onCreate()
old line ListView listView = (ListView)findViewById(R.id.listing);
New line listView = (ListView)findViewById(R.id.listing);

How to improve ListView's loading time faster?

I implemented my ListView using custom adapter extended from ArrayAdapter.
My problem is sometimes ListView is loaded slowly. That means a blank activity is loaded first without the ListView, then the ListView comes out. At worst case, I am prompted to "force closed or wait". I like to improve that slow loading as it is annoying to the user.
But sometimes, loading is fast and almost immediate.
But I like to make sure my ListView design is correct and the design does not have any problem with that slow loading. So that this discussion will be useful for other people who are facing the same problem as mine.
My ListView is designed as follow.
Each ListItem has three components, thumbnail image, ID text, and arrow image as shown in the figure attached .
In loading process of the ListView, (1)All ID text are retrieved from the database and populated into a ListArray List<String> listIDs
public class MyListFragment extends ListFragment implements OnItemClickListener {
dbHelper = new TrackerDBAdapter(getActivity());
dbHelpLatLong = new LatLogDBAdapter(getActivity());
dbHelpNotification = new NotificationDatabaseAdapter(getActivity());
dbHelper.open();
Cursor cursor = dbHelper.fetchAllTrackerInTheList();
listIDs = new ArrayList<String>();
activationStatus = new ArrayList<String>();
thisListFragmentContext = getActivity();
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
listIDs.add(cursor.getString(1));
}
dbHelper.close();
(2)Then my custom list adapter is called.
adapter = new customList_Adaptor(thisListFragmentContext,
R.layout.list_row, listIDs, this);
}
That is the loading process inside my `ListFragment`.
(3) The following class is my custom ArrayAdapter and I implemented to load thumbnail ImageView using AsyncTask. My query are
(i)I still have retrieving ID text from database, and loading arrow image. Should I put those processes into AsyncTask as well?
(ii)If I need it, should I implement another AsyncTask or use the same AsyncTask used for thumbnail image loading?
(iii)Among these, which aspect of the program design I still can improve that is suspicious to my slow loading?
public class customList_Adaptor extends ArrayAdapter<String>{
protected static final int CAMERA_REQUEST = 0;
private TrackerDBAdapter dbHelper;
private Context context;
private List<String> listIDs = new ArrayList<String>();
private List<String> activationState = new ArrayList<String>();
public MyListFragment mMyListFragment;
public customList_Adaptor(Context context, int textViewResourceId,
List<String> objects, List<String> activationStatus, MyListFragment mMyListFragment) {
super(context, textViewResourceId, objects);
this.setContext(context);
this.listIDs = objects;
this.activationState = activationStatus;
this.mMyListFragment= mMyListFragment;
dbHelper = new TrackerDBAdapter(context);
}
#Override
public int getCount() {
// TODO Auto-generated method stub
if(listIDs != null)
return listIDs.size();
else
return 0;
}
#Override
public String getItem(int arg0) {
// TODO Auto-generated method stub
if(listIDs != null)
return listIDs.get(arg0);
else
return null;
}
#Override
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return arg0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
ViewHolder viewHolder=new ViewHolder();
LayoutInflater inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if(vi==null){
vi = inflater.inflate(R.layout.list_row, parent, false);
viewHolder.id=(TextView)vi.findViewById(R.id.title);
viewHolder.thumbnailImage=(ImageView)vi.findViewById(R.id.list_image);
viewHolder.activationStatus = (TextView)vi.findViewById(R.id.activated);
//lazy load image
BitmapWorkerTask task = new BitmapWorkerTask(viewHolder.thumbnailImage);
task.execute(position);
viewHolder.arrow=(ImageView)vi.findViewById(R.id.list_arrow);
vi.setTag(viewHolder);
}
else
viewHolder=(ViewHolder) vi.getTag();
viewHolder.thumbnailImage.setOnClickListener(new onMyClick(position));
// Setting all values in listview
viewHolder.id.setText(listIDs.get(position));
if(activationState.get(position).equals("Not activated yet")){
viewHolder.activationStatus.setText(activationState.get(position));
viewHolder.activationStatus.setTextColor(android.graphics.Color.GRAY);
}
else if(activationState.get(position).equals("Activated"))
viewHolder.activationStatus.setText("");
return vi;
}
public class onMyClick implements OnClickListener {
private final int pos;
public onMyClick(int pos) {
this.pos = pos;
}
#Override
public void onClick(View v) {
MyListFragment.clickedimageView = (ImageView) v.findViewById(R.id.list_image);
mMyListFragment.imagepos(pos);
}
}
public Context getContext() {
return context;
}
public void setContext(Context context) {
this.context = context;
}
//Lazy image update
class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private int data = 0;
public BitmapWorkerTask(ImageView imageView) {
// Use a WeakReference to ensure the ImageView can be garbage collected
imageViewReference = new WeakReference<ImageView>(imageView);
}
// Decode image in background.
#Override
protected Bitmap doInBackground(Integer... params) {
setData(params[0]);
Bitmap bitmap = null;
dbHelper.open();
Cursor mCursor = dbHelper.getImagebyIDnumber(getData());
byte[] img_bytes = mCursor.getBlob(13);
bitmap = BitmapFactory.decodeByteArray(img_bytes, 0, img_bytes.length);
dbHelper.close();
return bitmap;
}
// Once complete, see if ImageView is still around and set bitmap.
#Override
protected void onPostExecute(Bitmap bitmap) {
if (imageViewReference != null && bitmap != null) {
final ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
}
}
public class ViewHolder {
TextView id;
TextView activationStatus;
ImageView thumbnailImage;
ImageView arrow;
}
I did a few things to make it faster in loading the app.
I am not sure which one is the solution.
(1) I load all data from sql database including text and thumbnail images using AsyncTask.
(2) I change thumbnail image format from png to jpg.
(3) Then I clear the cache manually.
The app looks like faster in loading, but sometimes it is still slow. Most of the times, it is faster than before.
I am still making improvement to my app.
Thanks

android issue with populating the list item in a ListView

In my application, to populating a ListView i am using custom adapter, because one listitem consists of 3 TextViews and 1 ImageView.
Everytime images are fetched from url.
So when i am launching this activity its taking much time,because its downloading all images then populating the lists.
So i want without images list should populate first having only Textviews and after that only images should come.
How can i do that?
By loading your images with an AsyncTask
example directly from documentation:
public void onClick(View v) {
new DownloadImageTask().execute("http://example.com/image.png");
}
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
/** The system calls this to perform work in a worker thread and
* delivers it the parameters given to AsyncTask.execute() */
protected Bitmap doInBackground(String... urls) {
return loadImageFromNetwork(urls[0]);
}
/** The system calls this to perform work in the UI thread and delivers
* the result from doInBackground() */
protected void onPostExecute(Bitmap result) {
mImageView.setImageBitmap(result);
}
}
you have to create a lazy image loader using async task.
by doing that, all your list view will be populated. and when the images are fetched, they are updated into the list views asynchronously.
Here is a link - http://iamvijayakumar.blogspot.com/2011/06/android-lazy-image-loader-example.html
You can use lazy load images like this:
https://github.com/thest1/LazyList
Lazy load of images in ListView
The basic Idea is to have a loading image already within your app.
Then use an asyncTask or a thread to load image.
Some code to start with :
Adapter
public class ImageAdapter extends BaseAdapter {
private static final String TAG = "Image Adapter";
int mGalleryItemBackground;
private Context mContext;
private GridView mView;
/** URL-Strings to some remote images. */
private String[] mRemoteImagesURL ;
private Bitmap[] loadedImages;
public ImageAdapter(Context c,String[] remoteImagesURL,GridView v) {
mContext = c;
TypedArray attr = mContext.obtainStyledAttributes(R.styleable.HelloGallery);
mGalleryItemBackground = attr.getResourceId(R.styleable.HelloGallery_android_galleryItemBackground, 0);
attr.recycle();
mView = v;
mRemoteImagesURL=remoteImagesURL;
loadedImages = new Bitmap[mRemoteImagesURL.length];
}
public int getCount() {
return mRemoteImagesURL.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater infalInflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = infalInflater.inflate(R.layout.gallery_item, null);
}
ImageView imageView = (ImageView) convertView.findViewById(R.id.FrontImageView);
/* when image is already down-loaded then load that image */
if(loadedImages[position]!=null)
imageView.setImageBitmap(loadedImages[position]);
else
imageView.setImageResource(R.drawable.loading);
imageView.setBackgroundResource(mGalleryItemBackground);
return convertView;
}
public void loadImage(int position){
Bitmap bm;
try {
/* Open a new URL and get the InputStream to load data from it. */
URL aURL = new URL(mRemoteImagesURL[position]);
URLConnection conn = aURL.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
/* Buffered is always good for a performance plus. */
BufferedInputStream bis = new BufferedInputStream(is);
/* Decode url-data to a bitmap. */
bm = BitmapFactory.decodeStream(bis);
bis.close();
is.close();
loadedImages[position] =bm;
} catch (Exception e) {
Log.e(TAG, "Remote Image Load Exception"+e);
}
}
public void setLoadedImage(int position)
{
Log.d(TAG, "Position "+position);
View childView= mView.getChildAt(position);
if(loadedImages[position]!=null && childView != null)
{
ImageView imageView= (ImageView) childView.findViewById(R.id.FrontImageView);
imageView.setImageBitmap(loadedImages[position]);
}
}
}
private void updateImagesAsThread() {
Thread t = new Thread()
{
public void run()
{
try {
for(int i=0;i<imageAdapter.getCount();i++)
{
imageAdapter.loadImage(i);
listAdapterHandler.sendEmptyMessage(i);
}
}
catch (Exception e) {
// TODO: handle exception
Log.e(TAG,"UpdateImageAsThread "+e);
}
}
};
t.start();
}
private Handler listAdapterHandler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
switch (msg.what)
{
case -1:
Log.d(TAG, "here in the handle...");
break;
default:
Log.d(TAG, "here in the handle default...");
imageAdapter.setLoadedImage(msg.what);
//imageAdapter.notifyDataSetChanged();
break;
}
}
};

Categories

Resources