Search code examples
javaandroidlistviewandroid-fragmentsinfinite

How to do some kind of lazy load in my listview android studio


I created one fragment and I'm populating a list view in it using Retrofit for network connection and get request and I created custom adapter to populate list view:

public class TransactionsAdapter extends BaseAdapter {
ArrayList<Transactions> transactions;


public TransactionsAdapter(ArrayList<Transactions> transactions) {
    this.transactions=transactions;
}

@Override
public int getCount() {
    if (transactions.size()<20) {
        return transactions.size();
    }else return 20;

}

@Override
public Object getItem(int position) {
    return transactions.get(position);
}
@Override
public long getItemId(int position) {
    return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View view=null;
    ViewHolder viewHolder = null;

    if(convertView == null)
    {
        view = LayoutInflater.from(parent.getContext()).inflate(R.layout.izvjestaji_item,parent,false);
        viewHolder = new ViewHolder(view);
        view.setTag(viewHolder);

    }
    else{
        view = convertView;
        viewHolder= (ViewHolder) view.getTag();

    }

    Transactions transactions = (Transactions) getItem(position);

    if(transactions != null) {

        viewHolder.datum.setText(transactions.getShortDate());
        viewHolder.partner.setText(transactions.getMerchantName());
        String doublestring=Double.toString(transactions.getTransactionPointsAmount());
        String doublestring1=Double.toString(transactions.getSalesAmount());
        viewHolder.iznos.setText(doublestring1);
        viewHolder.brojbodova.setText(doublestring);
    }

    return view;
}


private class ViewHolder{
    TextView datum;
    TextView partner;
    TextView iznos;
    TextView brojbodova;

    public ViewHolder(View view) {
        this.datum = (TextView) view.findViewById(R.id.izvjestaji_datum);
        this.partner = (TextView) view.findViewById(R.id.izvjestaji_partner);
        this.iznos = (TextView) view.findViewById(R.id.izvjestaji_iznos);
        this.brojbodova=(TextView)view.findViewById(R.id.izvjestaji_brojbodova);
    }
}
}

I have created 2 layouts for item and for list view and It's all working like it should. Now I need to add some kind of lazy load or something simpler because there is a chance that server will return a lot of data and I want to show them like 20 by 20 to increase network efficient . This is my fragment code:

    public class Izvjestaji extends Fragment {
   // The onCreateView method is called when Fragment should create its View   
   object hierarchy,
 // either dynamically or via XML layout inflation.
 ListView list;
 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle   
 savedInstanceState) {
    // Defines the xml file for the fragment


    return inflater.inflate(R.layout.izvjestaji, parent, false);

 }

// This event is triggered soon after onCreateView().
// Any view setup should occur here.  E.g., view lookups and attaching view          
listeners.
@Override
 public void onViewCreated(View view, Bundle savedInstanceState)  {
    list=(ListView)view.findViewById(R.id.izvjestaji_list);
    showList();
    // Setup any handles to view objects here
    // EditText etFoo = (EditText) view.findViewById(R.id.etFoo);

 }
 public void showList(){

    NetworkSDK.getInstance().getTransactions(new     
    Callback<List<Transactions>>() {
        @Override
        public void onResponse(Call<List<Transactions>> call,        
        Response<List<Transactions>> response) {
            if(response.isSuccess()){
                Log.d("Data", String.valueOf(response.isSuccess()));
                TransactionsAdapter transactionsAdapter=new 
        TransactionsAdapter((ArrayList<Transactions>)response.body());
                list.setAdapter(transactionsAdapter);


            }
        }

        @Override
        public void onFailure(Call<List<Transactions>> call, Throwable t) {
            Log.d("Error","Def error");

        }
    });
 }
 }

This is my call from Network SDK in retrofit

    public void getTransactions(Callback<List<Transactions>>callback){
    Call<List<Transactions>>call =                                                                                                           
    BaseClient.getService().getTransactions(4,2016);
            call.enqueue(callback);
}

From all of this I get a listview in my fragment that show all available transactions that I want to show but I need to limit it to about 20 and when user Swipe bottom it need to show another 20 and so on. I got some idea like to send some index number when user swipe or similar but I'm sure that there is some easier way because I'm not that good with android.

I also tried things like endless adapter but I am not allowed to use libraries that are not really popular like retrofit or volley and this one: https://github.com/commonsguy/cwac-endless is not providing suppor anymore and I'm not even sure is it still valid


Solution

  • use OnScrollListener to detect whether list scrolled to down or not . and then load data .

      mListView.setOnScrollListener(new OnScrollListener() {
    
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
    
        }
    
        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            if (mListView.getAdapter() == null)
                return ;
    
            if (mListView.getAdapter().getCount() == 0)
                return ;
    
            int l = visibleItemCount + firstVisibleItem;
            if (l >= totalItemCount && !isLoading) {
                // It is time to add new data. We call the listener
                isLoading = true;
                loadYourData();
            }
        }
    });
    

    after loading data don't forgot to refresh your list in adapter.

    public void updateInUi() {
    
        // send your request and get list of updated items
        List<> newItems = getYourUpdatedListHere()
        yourDataList.addAll(newItems);
        adapter.notifyDataSetChanged();
    }