I have three swipable tabs. In the first tab, I have a listview with more than 1000 items.
I tried to fill the list using Asynctask and Runnable and I have no problem with that.
The problem is when I am trying to assign the adapter to the listview. I noticed no matter how many items are in the adapter, whether it is 1 or 1000, when it tries to do: listView.setAdapter(adapter), it skips around 30 frames...
Since listView.setAdapter(adapter) is used in the first tab, whenever the user tries to enter that tab, UI freezes for some milliseconds. Although it is not a serious problem, but I don't like it.
The question is: Is this normal that when we invoke listView.setAdapter(adapter) the UI freezes for some milliseconds and skips some frames? Is there not anyway to fix this?
Am I Clear?
Carpet_handler ch; // my db handler
ListView listview;
public ArrayList<CarpetGen> carpetGens;
CarpetAdapter adapter;
boolean loadingMore=false;
int offset;
Context ctx;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_first_page_customers, container, false);
ch=new Carpet_handler(getActivity()); // db handler
listview = (ListView) rootView.findViewById(R.id.listView2);
ctx=this.getActivity();
carpetGens = new ArrayList<CarpetGen>();
offset=0;
adapter = new CarpetAdapter(getActivity(), R.layout.row, carpetGens);
listview.setAdapter(adapter); // adapter is empty first time, runnable fills it
listview.setOnItemClickListener(myClickListener);
//Here is where the magic happens
listview.setOnScrollListener(new OnScrollListener(){
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
//what is the bottom iten that is visible
int lastInScreen = firstVisibleItem + visibleItemCount;
//is the bottom item visible & not loading more already ? Load more !
if((lastInScreen == totalItemCount) && !(loadingMore)){
Thread thread = new Thread(null, loadMoreListItems);
thread.start();
}
}
});
return rootView;
}
//Runnable to load the items
private Runnable loadMoreListItems = new Runnable() {
@Override
public void run() {
//Set flag so we cant load new items 2 at the same time
loadingMore = true;
//Reset the array that holds the new items
carpetGens= new ArrayList<CarpetGen>();
carpetGens.addAll(ch.getAllCustomerCarpets1(getActivity().getIntent().getIntExtra("recordid", -1), offset));
offset+=15;
//Done! now continue on the UI thread
if(getActivity()==ctx)
getActivity().runOnUiThread(returnRes);
}
};
//Since we cant update our UI from a thread this Runnable takes care of that!
private Runnable returnRes = new Runnable() {
@Override
public void run() {
//Loop thru the new items and add them to the adapter
if(carpetGens != null && carpetGens.size() > 0){
for(int i=0;i < carpetGens.size();i++)
adapter.add(carpetGens.get(i));
}
adapter.notifyDataSetChanged();
loadingMore = false;
}
};
Here is my adapter:
public class CarpetAdapter extends ArrayAdapter<CarpetGen> {
private final Context context;
private final int rowResourceId;
//private final String[] Ids;
private final ArrayList<CarpetGen> Objects;
public CarpetAdapter(Context context, int textViewResourceId, ArrayList<CarpetGen> objects){//Arr[] objects) {
super(context, textViewResourceId, objects);
// TODO Auto-generated constructor stub
this.context = context;
this.rowResourceId = textViewResourceId;
this.Objects = objects;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
View rowView = convertView;
CarpetGen i = Objects.get(position);
if (rowView == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
rowView = inflater.inflate(R.layout.row, parent, false);
//TextView textView = (TextView) rowView.findViewById(R.id.textView);
//textView.setText(i.Result_String);
holder = new ViewHolder();
holder.title = (TextView) rowView
.findViewById(R.id.textView);
rowView.setTag(holder);
} else {
holder = (ViewHolder) rowView.getTag();
}
holder.title.setText(i.Result_String);
return rowView;
}
static class ViewHolder {
TextView title;
} }
I think it's perfectly normal. Keep in mind that it has to refresh the layout, even if it has zero elements, when you call the setAdapter()
method, you're doing some operations which depends on your implementation, but basically it's not a 0-second-miracle. As @laalto suggested, there also might be a bottleneck in the custom adapter implementation, so you might want to consider doing some work in Thread
s (or basically the AsyncThread
). But as I said, I'd not worry about it (overall, if this frame skipping was happening in a virtual device).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With