6

My adapter list is refreshing on broadcast receiver .

Everything is working fine if adapter list size is greater than 1 , means if my recyclerview has already one row shwoing then list refreshing just fine . But if list size goes from 0 to 1 then my adapter notify dataset Changed stop working . No data shows on recyclerview. I don't know why it is not working .

Recyclerview Class:

     @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        v = inflater.inflate(R.layout.job_recyclerview, container, false);
getActivity());
        initialise(v);
        init();
        showNoTaskMessage();
        new loadListTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
        mMyBroadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                // Here you can refresh your listview or other UI


                SlidingTab.slidingTab.getTabAt(0).setText("New (" + SingleTon.getInstance().getNewjob() + ")");
                SlidingTab.slidingTab.getTabAt(1).setText("In Progress (" + SingleTon.getInstance().getInprogressjob() + ")");;
                SlidingTab.slidingTab.getTabAt(2).setText("Completed (" + SingleTon.getInstance().getCompletedjob() + ")");

            }

        };

        try {

            IntentFilter filter = new IntentFilter("newJob");
            LocalBroadcastManager.getInstance(context).registerReceiver(mMyBroadcastReceiver,
                    filter);

        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
        return v;
    }

Adapter class :

 public JobAdapter(ArrayList<Info> myDataset, Context context) {
        this.mDataset = myDataset;
        this.mAct = context;
    }

    public void addApplications(ArrayList<Info> candidates) {
        if (this.filterList == null) {
            filterList = new ArrayList<>();
        }
        this.mDataset.clear();
        this.mDataset.addAll(candidates);
        this.filterList.addAll(mDataset);
        this.notifyItemRangeInserted(0, candidates.size() - 1);

    }

    public void clearApplications() {
        int size = this.mDataset.size();
        if (size > 0) {
            for (int i = 0; i < size; i++) {
                mDataset.remove(0);
                filterList.remove(0);
            }

            this.notifyItemRangeRemoved(0, size);
        }
    }

    @Override
    public int getItemViewType(int position) {
        return VIEW_NORMAL;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.single_job_card, parent, false);
        ViewHolder fh = new ViewHolder(v);
        return fh;
    }

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

//        holder.jobPhone.setText(mDataset.get(position).mobileNo);
        holder.jobNumber.setText(mDataset.get(position).jobNumber);
        holder.jobTime.setText(mDataset.get(position).time);
        holder.jobAddress.setText(mDataset.get(position).address);
//        holder.jobInstructionText.setText(mDataset.get(position).spclInstruction);

        if (mDataset.get(position).jobStatus != null && mDataset.get(position).jobStatus.equalsIgnoreCase("Completed")) {
            holder.endsat.setText("Submitted at");
            holder.jobTime.setText(mDataset.get(position).completedOnString);
            holder.jobTimeLeft.setVisibility(View.INVISIBLE);
            holder.timerImage.setVisibility(View.INVISIBLE);

        } else {
            if (mDataset.get(position).status.equalsIgnoreCase("Active")) {
                holder.jobTimeLeft.setText(mDataset.get(position).appointmentTime);
            } else {
                holder.jobTimeLeft.setText("-" + mDataset.get(position).appointmentTime);
            }
        }

        holder.jobLayout1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SingleTon.getInstance().setWorkDescHolder(mDataset.get(position).descHolder);
                FragmentManager fragmentManager = ((FragmentActivity) mAct).getSupportFragmentManager();
                FragmentTransaction ft = ((FragmentActivity) mAct).getSupportFragmentManager().beginTransaction();
                ft.setCustomAnimations(R.anim.glide_fragment_horizontal_in, R.anim.glide_fragment_horizontal_out);
                ft.replace(R.id.content_frame1, new DetailsFragment(), "persondetails");
                ft.addToBackStack("persondetails");

                // Start the animated transition.
                ft.commit();

            }
        });


    }

    @Override
    public int getItemCount() {
        return mDataset.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        private TextView jobNumber, jobTimeLeft, jobStatus, jobAddress, jobEmail, jobPhone, timeTimer, jobInstructionText, jobTime, endsat;
        private ImageView timerImage;
        private FrameLayout frameLayout;
        private CardView cardView;
        private LayoutRipple jobLayout1;

        public ViewHolder(View v) {
            super(v);
            this.jobNumber = (TextView) v.findViewById(R.id.job_number);
            this.jobTime = (TextView) v.findViewById(R.id.job_time);
            this.jobTimeLeft = (TextView) v.findViewById(R.id.job_timertext);
            this.timerImage = (ImageView) v.findViewById(R.id.timerimage);
            this.cardView = (CardView) v.findViewById(R.id.card_view);
//            this.jobStatus = (TextView) v.findViewById(R.id.job_status);
            this.jobAddress = (TextView) v.findViewById(R.id.job_addresstext);
//            this.jobInstructionText = (TextView) v.findViewById(R.id.instruction_text);
//            this.jobLayout = (LayoutRipple)v.findViewById(R.id.job_cardLayout);
            this.jobLayout1 = (LayoutRipple) v.findViewById(R.id.cardLayout1);
            this.endsat = (AppCompatTextView) v.findViewById(R.id.endsat);
            this.jobNumber.setTypeface(Utils.RegularTypeface(mAct));
            this.jobAddress.setTypeface(Utils.RegularTypeface(mAct));
            this.jobTimeLeft.setTypeface(Utils.RegularTypeface(mAct));
            this.jobTime.setTypeface(Utils.RegularTypeface(mAct));
        }
    }
}

Please help me finding the bug or some other approach . Thanks

young_08
  • 1,196
  • 2
  • 13
  • 35
  • See if this line is problematic `this.notifyItemRangeInserted(0, candidates.size() - 1);` – random Aug 09 '16 at 06:45
  • @random what should i change it to? – young_08 Aug 09 '16 at 06:46
  • 3
    second arg in the method is item count but if your candidates size is one subtracting one means 0 item count. try changing second arg to just candidates.size() – random Aug 09 '16 at 06:49
  • @random no still not working – young_08 Aug 09 '16 at 06:55
  • if this.notifyItemRangeInserted(0, candidates.size()) doesn't work then try changing it to notifyDataSetChanged and check if it works. If it does then there might be a problem with parameters passed in notifyItemRangeInserted. – Gautam Aug 09 '16 at 07:01
  • try to log `mDataset.size()` inside `getItemCount()` and see if it really updates every time you expect to refresh your recyclerview – random Aug 09 '16 at 07:01
  • @random i have changed this.notifyItemRangeInserted(0, candidates.size()) to this.notifydatasetchnaged . but still not working though mdatasize showing correct count . – young_08 Aug 09 '16 at 07:15
  • try to update `reyclerview` in a UI thread from broadcast receiver as described here http://stackoverflow.com/questions/22869928/android-broadcastreceiver-onreceive-update-textview-in-mainactivity – random Aug 09 '16 at 07:24
  • @random but i am receiving my broadcast in recyclerview class only then getting instance of it and all i think might be not a right way. – young_08 Aug 09 '16 at 07:29
  • @Gautam i have changed this.notifyItemRangeInserted(0, candidates.size()) to this.notifydatasetchnaged – young_08 Aug 09 '16 at 07:32
  • Its not about where your broadcast receiver is. Once you receive your data in receiver, UI should be updated on UI thread else changes wont reflect. Give it a chance and let us know if it helps. – random Aug 09 '16 at 10:08
  • @random ohkay i will try . So,where should i put the updateMethod in adapter? – young_08 Aug 09 '16 at 10:13
  • @random still not working . – young_08 Aug 09 '16 at 10:22
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/120500/discussion-between-random-and-young-08). – random Aug 09 '16 at 10:23
  • In your broadcastreceiver, the only real difference between if/else is how you add the list to addApplications, why don't you first try to just directly insert `SingleTon.getInstance().getInfoArrayList()` just like your if-part, comment out that addAll part for now. – TWL Aug 12 '16 at 23:41

7 Answers7

1

Call the data loading task inside the onReceive() of BroadcastReceiver

    mMyBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            // Here you can refresh your listview or other UI
           new loadListTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

            SlidingTab.slidingTab.getTabAt(0).setText("New (" + SingleTon.getInstance().getNewjob() + ")");
            SlidingTab.slidingTab.getTabAt(1).setText("In Progress (" + SingleTon.getInstance().getInprogressjob() + ")");;
            SlidingTab.slidingTab.getTabAt(2).setText("Completed (" + SingleTon.getInstance().getCompletedjob() + ")");

        }

    };

And also do following changes in your Adapter class.

   public void addApplications(ArrayList<Info> candidates) {
        if (this.filterList == null) {
            filterList = new ArrayList<>();
        }
        this.mDataset.clear();
        this.mDataset.addAll(candidates);
        this.filterList.addAll(mDataset);
        this.notifyItemRangeInserted(0, candidates.size());

    }

    public void clearApplications() {
        int size = this.mDataset.size();
        if (size > 0) {
            for (int i = 0; i < size; i++) {
                mDataset.remove(i);
                filterList.remove(i);
            }

            this.notifyItemRangeRemoved(0, size);
        }
    }

Hope that works!

Amresh
  • 2,098
  • 16
  • 20
0

Change this:

mMyBroadcastReceiver = new BroadcastReceiver() {
                    @Override
                    public void onReceive(Context context, Intent intent) {
                        // Here you can refresh your listview or other UI
                        recycleAdapter.addItems(SingleTon.getInstance()
                                         .getInfoArrayList());

                        // I'm assuming your "SingleTon.getInstance().getInfoArrayList()" is the received data.
                    }

On your Adapter

public void addItems(List<Info> itemsList) {
    // This check could be avoided if you declared your mDataset final
    if(mDataset == null) {
        mDataset = new ArrayList<>();
    }

    int prevSize = mDataset.size();
    mDataset.addAll(itemsList);
    notifyItemRangeInserted(prevSize, itemsList.size());
}
Joaquim Ley
  • 4,038
  • 2
  • 24
  • 42
0

You shouldn't call notifyDataSetChanged() after this.notifyItemRangeInserted(0, candidates.size() - 1); try something like this:

put this method to your adapter class

public void setData(ArrayList<Info> infos) {
   this.mDataset = infos;
   notifyDataSetChanged();
}

and call it like this:

ArrayList<Info> list = SingleTon.getInstance().getInfoArrayList().isEmpty();
if (list != null && !list.isEmpty()) {
    recycleAdapter.setData(list);
}

correct this method in your adapter

@Override
public int getItemCount() {
    return mDataset != null && !mDataset.isEmpty() ? mDataset.size() : 0;
}
MrOnyszko
  • 847
  • 9
  • 13
0

Base on your code, we need a variable list to store your info data.

//Declare the info list
private ArrayList<Info> mInfos = new ArrayList<Info>() 

In your onCreateView(), set mInfos to your recycleAdapter

recycleAdapter =  new JobAdapter(mInfos, getActivity());
recyclerView.setAdapter(recycleAdapter);

So, every time you want to set new info list. Just assign it to mInfos and make sure, you clear your previous list data to avoid duplicate data.

mInfos.clear()
mInfos.addAll(SingleTon.getInstance().getInfoArrayList());
//refresh data
recycleAdapter.notifyDataSetChanged();
THANN Phearum
  • 1,969
  • 22
  • 19
0

I am not sure where you are using clearApplications() in JobAdapter.class. But, it seems to be wrong. In the for-loop, you are trying to remove the value at index 0 every time rather than index 'i'. Hope this helps.

Bharat
  • 342
  • 3
  • 7
-1

when you are using custom adapter then notifyDatasetChange() not called from outside that adapter so make addItem function in adapter and add new List in Adapter list and call notifyDataSetChanged

public void addItem(List<Model> list) {
    if (lit != null) {
        clear();
        adapterList.addAll(list);

    }

    notifyDataSetChanged();
}
-1

Do Change In your recyclerview class.

//Change condition ">1" to "!=null"

if (SingleTon.getInstance().getInfoArrayList().size() != null) {
recycleAdapter.addApplications(SingleTon.getInstance().getInfoArrayList());
recycleAdapter.notifyDataSetChanged();

and then do change in your adapter.

public void addApplications(ArrayList<Info> candidates) {
    if (this.filterList == null) {
        filterList = new ArrayList<>();
    }
    this.mDataset.clear();
    this.mDataset.addAll(candidates);
    this.filterList.addAll(mDataset);
    this.notifyItemRangeInserted(0, mDataset.size()); //notify to mDataset
}

hope this will work!

Uttam Panchasara
  • 5,735
  • 5
  • 25
  • 41