在Android recyclerview中逐个删除页面中的所有项目不会加载下一组数据

时间:2017-12-04 01:21:21

标签: android android-recyclerview

我已经实现了recyclerview,它一次加载10个任务。完成每项任务后,我将使用完成的按钮删除任务。它加载第11项如果我在一个条件下滚动到底部,则必须至少有一个未完成的任务存在于页面上。如果我清除所有10个项目,它只显示我加载动画并没有任何反应。我必须关闭应用程序并再次打开以再次加载任务。

我已经为页面实现了PaginationActivity,PaginationAdapter和滚动侦听器。它会在您到达页面末尾时从本地数据库加载数据,并且您需要加载更多任务。

PaginationActivity.java

public class PaginationActivity extends AppCompatActivity {

private static final String TAG = "MainActivity";

PaginationAdapter adapter;
LinearLayoutManager linearLayoutManager;

public static ArrayList<String> reasonsdata = new ArrayList<String>();
public static String rslt="";
public static String[] reasons;
public static boolean chk = true;
public static String payTypeSelected;
public static String reasonSelected;
public static HashMap<String, EditText> drivernotesMap = new HashMap<String, EditText>();
public static HashMap<String, EditText> paynoteMap = new HashMap<String, EditText>();
public static HashMap<String, String> paytypeMap = new HashMap<String, String>();


RecyclerView rv;
ProgressBar progressBar;

private static final int PAGE_START = 0;
private boolean isLoading = false;
private boolean isLastPage = false;
private int TOTAL_PAGES;
private int currentPage = PAGE_START;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.pagination_main);
    fillspinner();

    rv = (RecyclerView) findViewById(R.id.main_recycler);
    progressBar = (ProgressBar) findViewById(R.id.main_progress);

    adapter = new PaginationAdapter(this);

    linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
    rv.setLayoutManager(linearLayoutManager);

    rv.setItemAnimator(new DefaultItemAnimator());

    rv.setAdapter(adapter);

    rv.addOnScrollListener(new PaginationScrollListener(linearLayoutManager) {
        @Override
        protected void loadMoreItems() {
            isLoading = true;
            currentPage += 1;

            // mocking network delay for API call
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    loadNextPage();
                }
            }, 1000);
        }

        @Override
        public int getTotalPageCount() {
            return TOTAL_PAGES;
        }

        @Override
        public boolean isLastPage() {
            return isLastPage;
        }

        @Override
        public boolean isLoading() {
            return isLoading;
        }
    });


    // mocking network delay for API call
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            loadFirstPage();
        }
    }, 1000);

}

private void fillspinner() {
    reasonsdata.clear();
    try
    {
        rslt="START";
        CallReasons cr = new CallReasons();
        cr.join();
        cr.start();
        while(rslt=="START") {
            try {
                Thread.sleep(10);
            }catch(Exception ex) {
            }
        }
    }
    catch (Exception ex) {
        ex.printStackTrace();
    }
    if(rslt == "Success"){
        reasonsdata.add("<--- Select Reason --->");
        for(int i =0; i< reasons.length;i++){
            reasonsdata.add(reasons[i]);
        }
    }
}

public void loadFirstPage() {
    Log.d(TAG, "loadFirstPage: ");
    TOTAL_PAGES = Run.getTotalPages();
    //List<Run> runs = Run.createRuns(adapter.getItemCount());
    List<Run> runs = Run.createRuns(adapter.getMaxID());
    progressBar.setVisibility(View.GONE);
    adapter.addAll(runs);

    if (currentPage <= TOTAL_PAGES) adapter.addLoadingFooter();
    else isLastPage = true;
}

public void loadNextPage() {
    Log.d(TAG, "loadNextPage: " + currentPage);
    //List<Run> runs = Run.createRuns(adapter.getItemCount());
    List<Run> runs = Run.createRuns(adapter.getMaxID());

    adapter.removeLoadingFooter();
    isLoading = false;

    adapter.addAll(runs);

    if (currentPage != TOTAL_PAGES) adapter.addLoadingFooter();
    else isLastPage = true;
}

}

PaginationAdapter.java

    public class PaginationAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private static final int ITEM = 0;
    private static final int LOADING = 1;

    private List<Run> runs = new ArrayList<>();
    private Context context;

    private boolean isLoadingAdded = false;

    private String cash = "CASH";
    private String cheque = "CHEQUE";

    SQLiteDatabase db;
    //PaginationActivity func_call;

    public PaginationAdapter(Context context) {
        this.context = context;
        runs = new ArrayList<>();
        //func_call = new PaginationActivity();
    }

    public List<Run> getRuns() {
        return runs;
    }

    public void setRuns(List<Run> runs) {
        this.runs = runs;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        RecyclerView.ViewHolder viewHolder = null;
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());

        switch (viewType) {
            case ITEM:
                viewHolder = getViewHolder(parent, inflater);
                break;
            case LOADING:
                View v2 = inflater.inflate(R.layout.item_progress, parent, false);
                viewHolder = new LoadingVH(v2);
                //viewHolder = getViewHolder(parent, inflater);
                //func_call.loadNextPage();
                break;
        }
        return viewHolder;
    }

    @NonNull
    private RecyclerView.ViewHolder getViewHolder(ViewGroup parent, LayoutInflater inflater) {
        RecyclerView.ViewHolder viewHolder;
        View v1 = inflater.inflate(R.layout.activity_main, parent, false);
        viewHolder = new RunVH(v1);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

        final Run run = runs.get(position);

        switch (getItemViewType(position)) {
            case ITEM:
                final RunVH runVH = (RunVH) holder;
                //adding text areas to show data
                //Completed task button
                runVH.btnSave.setOnClickListener(new View.OnClickListener() {
                    public void onClick(View v) {
                        Toast.makeText(context, "Mark as Completed", Toast.LENGTH_LONG).show();
                                    remove(run);

                                }

                            }
                        } catch (Exception ex) {
                            //pbbar.setVisibility(View.GONE);
                            ex.printStackTrace();
                        }
                    }
                });
                break;
            case LOADING:
                break;
        }

    }

    @Override
    public int getItemCount() {
        return runs == null ? 0 : runs.size();
    }

    //@Override
    public int getMaxID() {
        if(runs == null || runs.size() == 0){
            return 0;
        }else{
            Run test = runs.get(runs.size()-2);
            int maxid = (int) test.getProperty(0);
            return maxid;
        }
    }

    @Override
    public int getItemViewType(int position) {
        return (position == runs.size() - 1 && isLoadingAdded) ? LOADING : ITEM;
    }

    public void add(Run run) {
        runs.add(run);
        notifyItemInserted(runs.size() - 1);
    }

    public void addAll(List<Run> runList) {
        for (Run run : runList) {
            add(run);
        }
    }

    public void remove(Run run) {
        int position = runs.indexOf(run);
        if (position > -1) {
            runs.remove(position);
            notifyItemRemoved(position);
            notifyItemRangeChanged(position, runs.size());
        }
        /*if(runs.size() < 0){
            clear();
            func_call.loadNextPage();
        }*/
    }

    public void clear() {
        isLoadingAdded = false;
        while (getItemCount() > 0) {
            remove(getItem(0));
        }
    }

    public boolean isEmpty() {
        return getItemCount() == 0;
    }


    public void addLoadingFooter() {
        isLoadingAdded = true;
        add(new Run());
    }

    public void removeLoadingFooter() {
        isLoadingAdded = false;

        int position = runs.size() - 1;
        Run item = getItem(position);

        if (item != null) {
            runs.remove(position);
            notifyItemRemoved(position);
        }
    }

    public Run getItem(int position) {
        return runs.get(position);
    }

    protected class RunVH extends RecyclerView.ViewHolder {
        private TextView textEsky;
        private TextView textAdjusted;
        private TextView textAddress;
        private TextView textNew;
        private TextView textTrusted;
        private TextView textName;
        private TextView textMobile;
        private TextView textHome;
        private TextView textWork;
        private TextView payType;
        private EditText textPayNote;
        private EditText textDeliveryInst;
        private EditText textDriverNotes;
        private final Spinner reasons;
        private RadioGroup rg;
        private Button btnSave;
        private CheckBox IsDriverData;

        public RunVH(View itemView) {
            super(itemView);

            textEsky = (TextView) itemView.findViewById(R.id.idEsky);
            textAdjusted = (TextView) itemView.findViewById(R.id.idAdjusted);
            textAddress = (TextView) itemView.findViewById(R.id.idAddress);
            textNew = (TextView) itemView.findViewById(R.id.idNew);
            textTrusted = (TextView) itemView.findViewById(R.id.idTrusted);
            textName = (TextView) itemView.findViewById(R.id.idName);
            textMobile = (TextView) itemView.findViewById(R.id.idMobile);
            textHome = (TextView) itemView.findViewById(R.id.idHome);
            textWork = (TextView) itemView.findViewById(R.id.idWork);
            payType = (TextView) itemView.findViewById(R.id.idPayType);
            textPayNote = (EditText) itemView.findViewById(R.id.idPayNoteText);
            textDeliveryInst = (EditText) itemView.findViewById(R.id.idDeliInsText);
            textDriverNotes = (EditText) itemView.findViewById(R.id.idDriverNotesText);
            IsDriverData = (CheckBox) itemView.findViewById(R.id.idCheckBox);
            reasons = (Spinner) itemView.findViewById(R.id.idReason);
            rg = (RadioGroup) itemView.findViewById(R.id.Radiogroup);
            btnSave = (Button) itemView.findViewById(R.id.button);
        }
    }


    protected class LoadingVH extends RecyclerView.ViewHolder {

        public LoadingVH(View itemView) {
            super(itemView);
        }
    }


}

PaginationScrollListener.java

public abstract class PaginationScrollListener extends RecyclerView.OnScrollListener {

    LinearLayoutManager layoutManager;

    public PaginationScrollListener(LinearLayoutManager layoutManager) {
        this.layoutManager = layoutManager;
    }

    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);

        int visibleItemCount = layoutManager.getChildCount();
        int totalItemCount = layoutManager.getItemCount();
        int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition();

        if (!isLoading() && !isLastPage()) {
            if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount
                    && firstVisibleItemPosition >= 0) {
                loadMoreItems();
            }
        }
    }

    protected abstract void loadMoreItems();

    public abstract int getTotalPageCount();

    public abstract boolean isLastPage();

    public abstract boolean isLoading();
}

1 个答案:

答案 0 :(得分:0)

我可能是错的,但在我看来,只有当您召回loadNextPage()时,RecyclerView才会收到滚动事件。删除ViewHolders不会导致滚动事件。

如果您在PaginationAdapter上注册AdapterDataObserver,则可以在没有任何任务时收听删除/添加事件并触发加载。对remove(Run)中注释掉的代码进行一些小的更改,你可能会做同样的事情:

if (runs.isEmpty()) {
    func_call.loadNextPage();
}

编辑:

顺便问一下,您看到adapter = new PaginationAdapter(this);方法中您调用PaginationActivity.onCreate的位置了吗?这里的this是您的PaginationActivity,这意味着您可以将其分配到PaginationAdapter字段,如下所示:

/**
 * @param context the activity this adapter will appear in
 */
public PaginationAdapter(Context context) {
    this.context = context;
    runs = new ArrayList<>();
    func_call = (PaginationActivity)context;
}

这应该足以防止崩溃。为了更好地分离问题,您可能希望切换到基于AdapterDataObserver的逻辑(我认为这称为open/closed principle?可能?)。