1

I'm using SectionedRecyclerViewAdapter to create multiple sections in the recyclerview. The issue is when i trigger switchcompat i want both sections to get updated. It means whenever i change switchcompat state to checked i want the item to get removed from all apps list and get added to locked apps list and vice versa. In other words i want my fragment to get updated whenever i trigger switchcompat.

What is the best way to achieve it?

Fragment

public class AppListFragment extends Fragment {

    Context mContext;
    RecyclerView recyclerView;
    RecyclerView.Adapter adapter;
    RecyclerView.LayoutManager recyclerViewLayoutManager;

    private SectionedRecyclerViewAdapter sectionAdapter;

    public AppListFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment

        View appListView = inflater.inflate(R.layout.fragment_app_list,container,false);

        sectionAdapter = new SectionedRecyclerViewAdapter();

        List<AppItem> lockedAppItemList = getLockedAppList(inflater.getContext());
        List<AppItem> allAppItemList = getAllAppList(inflater.getContext());

        sectionAdapter.addSection(new SectionLockedApps("Locked Apps", inflater.getContext(),new AppManager(inflater.getContext()).getAllInstalledApkInfo(), lockedAppItemList,sectionAdapter));
        sectionAdapter.addSection(new SectionAllApps("All Apps", inflater.getContext(),new AppManager(inflater.getContext()).getAllInstalledApkInfo(), allAppItemList,sectionAdapter));

        try {
            recyclerView = (RecyclerView) appListView.findViewById(R.id.rv_applist);
            recyclerViewLayoutManager = new LinearLayoutManager(this.getContext());
            recyclerView.setLayoutManager(recyclerViewLayoutManager);
            //adapter = new AppsAdapter(inflater.getContext(), new AppManager(inflater.getContext()).getAllInstalledApkInfo());
            recyclerView.setAdapter(sectionAdapter);

        }catch (Exception ex){
            Log.i("exception",ex.getMessage());
        }

        return appListView;
    }

    @Override
    public void onResume() {
        super.onResume();

        if (getActivity() instanceof AppCompatActivity) {
            AppCompatActivity activity = ((AppCompatActivity) getActivity());
            if (activity.getSupportActionBar() != null) {
                activity.getSupportActionBar().setTitle(R.string.app_name);
            }
        }
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

        mContext = context;
    }

    private List<AppItem> getLockedAppList(Context ctx) {
        AppManager appManager = new AppManager(ctx);
        List<AppItem> appItemList = new ArrayList<>();
        List<String> apkPackInfoList = appManager.getAllInstalledApkInfo();

        for(String apkPackInfo:apkPackInfoList){
            String appName = appManager.getAppName(apkPackInfo);
            Drawable imageDrawable = appManager.getAppIconByPackageName(apkPackInfo);
            Boolean isLocked = appManager.isGuardEnabled(apkPackInfo);
            if(isLocked){
                appItemList.add(new AppItem(imageDrawable,appName,apkPackInfo,isLocked));
            }
        }

        return appItemList;
    }

    private List<AppItem> getAllAppList(Context ctx) {
        AppManager appManager = new AppManager(ctx);
        List<AppItem> appItemList = new ArrayList<>();
        List<String> apkPackInfoList = appManager.getAllInstalledApkInfo();

        for(String apkPackInfo:apkPackInfoList){
            String appName = appManager.getAppName(apkPackInfo);
            Drawable imageDrawable = appManager.getAppIconByPackageName(apkPackInfo);
            Boolean isLocked = appManager.isGuardEnabled(apkPackInfo);
            if(!isLocked){
                appItemList.add(new AppItem(imageDrawable,appName,apkPackInfo,isLocked));
            }
        }

        return appItemList;
    }
}

Locked Apps Section

public class SectionLockedApps extends StatelessSection {

    private SectionedRecyclerViewAdapter sectionAdapter;

    String title;
    boolean isGuardEnabled;
    Context ctxAppList;
    List<String> stringList;
    List<AppItem> appItemList;

    public SectionLockedApps(String title, Context ctx, List<String> stringList, List<AppItem> appItemList, SectionedRecyclerViewAdapter sectionAdapter) {
        super(SectionParameters.builder()
                .itemResourceId(R.layout.cardview_layout_applist)
                .headerResourceId(R.layout.section_header)
                .build());

        this.title = title;
        this.ctxAppList = ctx;
        this.stringList = stringList;
        this.appItemList = appItemList;
        this.sectionAdapter = sectionAdapter;
    }

    @Override
    public int getContentItemsTotal() {
        return appItemList.size();
    }

    @Override
    public RecyclerView.ViewHolder getItemViewHolder(View view) {
        return new ItemViewHolder(view);
    }

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

        final AppManager appManager = new AppManager(ctxAppList);
        final String applicationPackageName = appItemList.get(position).getPackageName();
        isGuardEnabled = appManager.isGuardEnabled(applicationPackageName);

        if (appItemList.size() > 0) {
            String ApplicationLabelName = appItemList.get(position).getAppName();
            Drawable drawable = appItemList.get(position).getImageDrawable();



            final ItemViewHolder itemHolder = (ItemViewHolder) holder;

            itemHolder.textView_App_Name.setText(ApplicationLabelName);

            //viewHolder.textView_App_Package_Name.setText(applicationPackageName);

            itemHolder.imageView.setImageDrawable(drawable);

            itemHolder.switchCompat.setChecked(isGuardEnabled);

            //Adding click listener on CardView to open clicked application directly from here .
            itemHolder.rootView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {

                    Intent intent = ctxAppList.getPackageManager().getLaunchIntentForPackage(applicationPackageName);
                    if (intent != null) {

                        ctxAppList.startActivity(intent);

                    } else {

                        Toast.makeText(ctxAppList, applicationPackageName + " Error, Please Try Again.", Toast.LENGTH_LONG).show();
                    }
                }
            });

            itemHolder.switchCompat.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    appManager.setGuard(applicationPackageName, isChecked);
                    //appItemList.get(position).setLocked(isChecked);

                }
            });
        }

    }

    @Override
    public RecyclerView.ViewHolder getHeaderViewHolder(View view) {
        return  new HeaderViewHolder(view);
    }

    @Override
    public void onBindHeaderViewHolder(RecyclerView.ViewHolder holder) {
        HeaderViewHolder headerHolder = (HeaderViewHolder) holder;

        if(appItemList.size()>0){
            headerHolder.tvTitle.setText(title);
        }else {
            headerHolder.tvTitle.setVisibility(View.GONE);
        }



    }

    private class HeaderViewHolder extends RecyclerView.ViewHolder {

        private final TextView tvTitle;

        HeaderViewHolder(View view) {
            super(view);
            tvTitle = (TextView) view.findViewById(R.id.tvTitle);
        }
    }

    private class ItemViewHolder extends RecyclerView.ViewHolder {

        private final View rootView;

        public TextView textView_App_Name;
        public ImageView imageView;
        public SwitchCompat switchCompat;

        ItemViewHolder(View view) {
            super(view);

            rootView = view;

            textView_App_Name = (TextView) view.findViewById(R.id.Apk_Name);
            imageView = (ImageView) view.findViewById(R.id.imgApplist);
            switchCompat = (SwitchCompat) view.findViewById(R.id.compatSwitch);

        }
    }

}

All Apps Section

public class SectionAllApps extends StatelessSection {

    String title;
    boolean isGuardEnabled;
    Context ctxAppList;
    List<String> stringList;
    List<AppItem> appItemList;
    String applicationPackageName;
    AppManager appManager;

    private SectionedRecyclerViewAdapter sectionAdapter;

    public SectionAllApps(String title, Context ctx, List<String> stringList, List<AppItem> appItemList, SectionedRecyclerViewAdapter sectionAdapter) {
        super(SectionParameters.builder()
                .itemResourceId(R.layout.cardview_layout_applist)
                .headerResourceId(R.layout.section_header)
                .build());

        this.title = title;
        this.ctxAppList = ctx;
        this.stringList = stringList;
        this.appItemList = appItemList;
        this.sectionAdapter = sectionAdapter;
    }

    @Override
    public int getContentItemsTotal() {
        return appItemList.size();
    }

    @Override
    public RecyclerView.ViewHolder getItemViewHolder(View view) {
        return new ItemViewHolder(view);
    }

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

        final AppManager appManager = new AppManager(ctxAppList);
        final String applicationPackageName = appItemList.get(position).getPackageName();
        isGuardEnabled = appManager.isGuardEnabled(applicationPackageName);

        if (appItemList.size() > 0) {
            String ApplicationLabelName = appItemList.get(position).getAppName();
            Drawable drawable = appItemList.get(position).getImageDrawable();



            final SectionAllApps.ItemViewHolder itemHolder = (SectionAllApps.ItemViewHolder) holder;

            itemHolder.textView_App_Name.setText(ApplicationLabelName);

            //viewHolder.textView_App_Package_Name.setText(applicationPackageName);

            itemHolder.imageView.setImageDrawable(drawable);

            itemHolder.switchCompat.setChecked(isGuardEnabled);

            //Adding click listener on CardView to open clicked application directly from here .
            itemHolder.rootView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {

                    Intent intent = ctxAppList.getPackageManager().getLaunchIntentForPackage(applicationPackageName);
                    if (intent != null) {

                        ctxAppList.startActivity(intent);

                    } else {

                        Toast.makeText(ctxAppList, applicationPackageName + " Error, Please Try Again.", Toast.LENGTH_LONG).show();
                    }
                }
            });

            itemHolder.switchCompat.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    appManager.setGuard(applicationPackageName, isChecked);

                    //appItemList.get(position).setLocked(isChecked);

                }
            });
        }
    }

    @Override
    public RecyclerView.ViewHolder getHeaderViewHolder(View view) {
        return new HeaderViewHolder(view);
    }

    @Override
    public void onBindHeaderViewHolder(RecyclerView.ViewHolder holder) {
        HeaderViewHolder headerHolder = (HeaderViewHolder) holder;

        headerHolder.tvTitle.setText(title);
    }

    private class HeaderViewHolder extends RecyclerView.ViewHolder {

        private final TextView tvTitle;

        HeaderViewHolder(View view) {
            super(view);
            tvTitle = (TextView) view.findViewById(R.id.tvTitle);
        }
    }

    private class ItemViewHolder extends RecyclerView.ViewHolder {

        private final View rootView;
        public ImageView imageView;
        public TextView textView_App_Name;
        public SwitchCompat switchCompat;


        ItemViewHolder(View view) {
            super(view);

            rootView = view;

            imageView = (ImageView) view.findViewById(R.id.imgApplist);
            textView_App_Name = (TextView) view.findViewById(R.id.Apk_Name);
            switchCompat = (SwitchCompat) view.findViewById(R.id.compatSwitch);
        }
    }
}

appManager.SetGuard() basically saves switchcompat's last state.

  • So you are passing the list of apps to the constructor of SectionLockedApps and SectionAllApps... first thing you should do now is to create methods to allow a certain app to be added and removed from them.. `public static addApp(String appName) { stringList.add(appName); }` – Gustavo Pagani Apr 07 '18 at 20:51
  • i want both sections to be updated at the same time. So, when i remove an item from 1 section it should be added to another one and the oposite – Elvin No Matter Apr 09 '18 at 05:13
  • sure, you need a way of adding apps from one section and removing from the other, so you need add and remove methods in your section classes, that's the first step, the second is to call them – Gustavo Pagani Apr 09 '18 at 09:06
  • does it mean that I have to pass 2 lists(locked and all) of apps in both sections? – Elvin No Matter Apr 09 '18 at 15:18
  • don't think you need to – Gustavo Pagani Apr 09 '18 at 17:12

1 Answers1

0

After some research I've found a solution for my issue. The solution was not to work with list of apps but to refresh the fragment. Basically I've created an interface that is used for both of my sections on scenario execute with method refresh(); and made an implementation inside my fragment

Codes are written below:

Interface

public interface IFragmentOperation {
    public void refresh();
}

Modifications in fargment

public class AppListFragment extends Fragment implements IFragmentOperation {
....

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    ...

    sectionAdapter.addSection(new SectionLockedApps("Locked Apps", inflater.getContext(),lockedAppItemList,this));
    sectionAdapter.addSection(new SectionAllApps("All Apps", inflater.getContext(),allAppItemList,this));

    ...
}

//Refresh fragment on switchcompat touched
@Override
public void refresh() {
    FragmentTransaction fragmentTransaction = getActivity().getSupportFragmentManager().beginTransaction();
    fragmentTransaction.detach(this).attach(this).commit();
}

}

As you can see I've implemented an interface with method refresh() and added an extra parameter this inside my sections cunstructor. This way I'm sending an interface implementation into my section classes.

Then in my section I simply create IFragmentOperation fragmentOperation; and assigning the value of fragmentOperation inside constructor

IFragmentOperation fragmentOperation;

public SectionLockedApps(String title, Context ctx,List<AppItem> appItemList,IFragmentOperation fragmentOperation) {
    super(SectionParameters.builder()
            .itemResourceId(R.layout.cardview_layout_applist)
            .headerResourceId(R.layout.section_header)
            .build());

    this.title = title;
    this.ctxAppList = ctx;
    this.appItemList = appItemList;
    this.fragmentOperation = fragmentOperation;
}

and use it wherever is needed like this fragmentOperation.refresh();

itemHolder.switchCompat.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        appManager.setGuard(applicationPackageName, isChecked);
        //appItemList.get(position).setLocked(isChecked);
        fragmentOperation.refresh();

    }
});

That's it. Hope it will help someone with related issue.