0

Each wallet in my recycler view has a settings activity, and I am able to delete a recycler item from it's settings activity using the code below

I'm trying to get the recycler view to update once i perform the delete function but i keep getting null pointer exceptions from my walletfragment

Settings.kt

 class WalletSettings : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.settings_activity)
        supportFragmentManager
                .beginTransaction()
                .replace(R.id.settings, SettingsFragment())
                .commit()
        supportActionBar?.setDisplayHomeAsUpEnabled(true)

        val txtName = findViewById<View>(R.id.title) as TextView
        txtName.text = "Settings"

        val subTitle = findViewById<View>(R.id.sub_title) as TextView
        subTitle.visibility = View.VISIBLE
        subTitle.text = intent.extras!!.getString("walletname")

        val leftImageView = findViewById<View>(R.id.go_back) as ImageView
        leftImageView.setImageResource(R.drawable.ic_action_navigation_arrow_back)
        leftImageView.setColorFilter(ContextCompat.getColor(applicationContext, R.color.colorPrimary))
        leftImageView.setOnClickListener { finish() }

        val rightImageView = findViewById<View>(R.id.notification) as ImageView
        rightImageView.visibility = View.INVISIBLE
    }

    class SettingsFragment : PreferenceFragmentCompat() {
        var walletsFragment: WalletsFragment? = null

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setHasOptionsMenu(true)
            walletsFragment = WalletsFragment()
            Log.i(TAG, "----------oncreate fragment $walletsFragment")
        }

        override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
            setPreferencesFromResource(R.xml.root_preferences, rootKey)

            val deleteWallet: Preference? = findPreference(getString(R.string.delete))
            deleteWallet!!.setOnPreferenceClickListener { //code for what you want it to do
                Toast.makeText(context, "Delete wallet clicked", Toast.LENGTH_SHORT).show();
                deleteWalletUser();
                true
            }

            val changePIN: Preference? = findPreference(getString(R.string.change_pin))
            changePIN!!.setOnPreferenceClickListener { //code for what you want it to do
                Toast.makeText(context, "Change PIN clicked", Toast.LENGTH_SHORT).show();
                true
            }

            val useFingerprint: Preference? = findPreference(getString(R.string.fingerprint))
            useFingerprint!!.setOnPreferenceClickListener { //code for what you want it to do
                Toast.makeText(context, "Use fingerprint clicked", Toast.LENGTH_SHORT).show();
                false
            }

        }


        private fun deleteWalletUser() {
            val walletID = requireActivity().intent.extras!!.getInt("walletid")
            val stringRequest: StringRequest = object : StringRequest(Method.DELETE, URLs.URL_USER_DELETE_WALLET + walletID,
                    Response.Listener { response ->
                        //                        progressBar.setVisibility(View.GONE);
                        try {
                            //converting response to json object
                            val obj = JSONObject(response)

                            //if no error in response
                            if (obj.getBoolean("success")) {
                                Toast.makeText(context, obj.getString("message"), Toast.LENGTH_SHORT).show()
                                requireActivity().finish()
                                Log.i(TAG, "----------ondelete $walletsFragment")

                                walletsFragment!!.updateWalletFragment()
                            } else {
                                Toast.makeText(context, obj.getString("message"), Toast.LENGTH_SHORT).show()
                            }
                        } catch (e: JSONException) {
                            e.printStackTrace()
                        }
                    },
                    Response.ErrorListener { error -> Toast.makeText(context, error.message, Toast.LENGTH_SHORT).show() }) {
                @Throws(AuthFailureError::class)
                override fun getParams(): Map<String, String> {
                    val params: MutableMap<String, String> = HashMap()
//                    params["wallet_name"] = walletID
                    return params
                }
            }
            VolleySingleton.getInstance(context).addToRequestQueue(stringRequest)
        }
    }

}

WalletFragment.java

      public class WalletsFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
    private RecyclerView mRecyclerView;
    private RecyclerView.Adapter mAdapter;
    private RecyclerView.LayoutManager mLayoutManager;

    private static String TAG = HomeFragment.class.getSimpleName();
    private TextView name;
    private TextView score;
    private SwipeRefreshLayout swipeRefreshLayout;

    private ArrayList<Wallet> userWalletList;

    private ProgressDialog progressDialog;

    boolean mIsRequest = false;

    private WalletsViewModel walletsViewModel;
    private ShimmerFrameLayout mShimmerViewContainer;

    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        walletsViewModel =
                ViewModelProviders.of(this).get(WalletsViewModel.class);
        View root = inflater.inflate(R.layout.fragment_wallets, container, false);
        TextView txtName = (TextView) root.findViewById(R.id.title);
        txtName.setText("Wallets");
        ImageView rightImageView = (ImageView) root.findViewById(R.id.notification);
        rightImageView.setImageResource(R.drawable.ic_action_account_balance_wallet);
        rightImageView.setColorFilter(ContextCompat.getColor(getContext(), R.color.colorPrimary));
        rightImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                    CreateWalletDialog createWalletFragment = new CreateWalletDialog();
                createWalletFragment.show(getChildFragmentManager(), createWalletFragment.getTag());

//                CustomAlertDialog cdd=new CustomAlertDialog(getActivity());
//                cdd.show();
//                Toast.makeText(getContext(),"Create a new wallet", Toast.LENGTH_SHORT).show();
            }
        });

        mShimmerViewContainer = root.findViewById(R.id.shimmer_view_container);
        mRecyclerView = (RecyclerView) root.findViewById(R.id.recycler_view);
        swipeRefreshLayout = (SwipeRefreshLayout) root.findViewById(R.id.swipe_refresh_layout);
        swipeRefreshLayout.setOnRefreshListener(this);
        swipeRefreshLayout.setColorSchemeColors(getResources().getColor(android.R.color.holo_green_dark),
                getResources().getColor(android.R.color.holo_red_dark),
                getResources().getColor(android.R.color.holo_blue_dark),
                getResources().getColor(android.R.color.holo_orange_dark));
        mRecyclerView.setHasFixedSize(true);
        SnapHelper helper = new LinearSnapHelper();
        helper.attachToRecyclerView(mRecyclerView);
        mLayoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
        mRecyclerView.setLayoutManager(mLayoutManager);

        //initializing the walletlist
        userWalletList = new ArrayList<>();
        loadUserWallets();

        return root;
    }


    private void loadUserWallets() {
//        swipeRefreshLayout.setRefreshing(true);
//        progressDialog = ProgressDialog.show(getActivity(), "Fetching All Time Earners","Please Wait....", true);
        /*
         * Creating a String Request
         * The request type is GET defined by first parameter
         * The URL is defined in the second parameter
         * Then we have a Response Listener and a Error Listener
         * In response listener we will get the JSON response as a String
         * */

        if(mIsRequest)
            return;
        mIsRequest= true;
        userWalletList.clear();

        User user = SharedPrefManager.getInstance(getContext()).getUser();
        StringRequest stringRequest = new StringRequest(Request.Method.GET, URLs.URL_USER_WALLET_LIST + user.getId(),
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        mIsRequest = false;
                        try {
                            //converting the string to json object
                            JSONObject object=new JSONObject(response);
                            //getting data array from json response object
                            JSONArray array=object.getJSONArray("data");

                            for(int i=0;i<array.length();i++) {

                                //getting wallet object from json array
                                JSONObject userWallets=array.getJSONObject(i);

                                //adding the wallet to wallet list
                                userWalletList.add(new Wallet(
                                        userWallets.getInt("id"),
                                        userWallets.getInt("user_id"),
                                        userWallets.getString("wallet_name"),
                                        userWallets.getInt("wallet_id"),
                                        userWallets.getInt("wallet_type"),
                                        userWallets.getDouble("balance")
                                ));
                            }

                            //creating adapter object and setting it to recyclerview
                            WalletAdapter adapter = new WalletAdapter(getActivity(),getChildFragmentManager(), userWalletList);
                            mRecyclerView.setAdapter(adapter);
                            swipeRefreshLayout.setRefreshing(false);
                            // stop animating Shimmer and hide the layout
                            mShimmerViewContainer.stopShimmerAnimation();
                            mShimmerViewContainer.setVisibility(View.GONE);
//                            progressDialog.dismiss();
                            adapter.notifyDataSetChanged();
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        mIsRequest = false;
//                        progressDialog.dismiss();
//                        swipeRefreshLayout.setRefreshing(false);
                        Toast.makeText(getContext(),"No Internet Connection", Toast.LENGTH_SHORT).show();
                    }
                });

        //adding our stringrequest to queue
        Volley.newRequestQueue(getContext()).add(stringRequest);
    }

    @Override
    public void onRefresh() {
        swipeRefreshLayout.setRefreshing(true);
        User user = SharedPrefManager.getInstance(getContext()).getUser();
        VolleySingleton.getInstance(getContext()).getRequestQueue().getCache().invalidate(URLs.URL_USER_WALLET_LIST + user.getId(), true);
        loadUserWallets();
    }

    public void updateWalletFragment(){
        loadUserWallets();
    }

    @Override
    public void onResume() {
        super.onResume();
        mShimmerViewContainer.startShimmerAnimation();
    }

    @Override
    public void onPause() {
        mShimmerViewContainer.stopShimmerAnimation();
        super.onPause();
    }

}

i get java.lang.NullPointerException: Attempt to invoke virtual method 'void java.util.ArrayList.clear()' on a null object reference at com.dreacot.dreacotwallet.ui.wallets.WalletsFragment.loadUserWallets(WalletsFragment.java:123)' on a null object reference

if i remove the code causing the null pointer, I get other nullpointers

i think the problem is i am creating a new instance of wallet fragment instead of reusing the old instance, if that's true, how can i do this reusing the old instance

might also be important to note, this is how i open the activity from the wallet adapter

WalletAdapter.java

 private void showSettingsActivity(RecyclerView.ViewHolder dataObjectHolder){
        Intent intent = new Intent(mCtx , WalletSettings.class);
        Bundle bundle = new Bundle();
        String walletName = userWalletList.get(dataObjectHolder.getAdapterPosition()).getWalletName();
        int walletID = userWalletList.get(dataObjectHolder.getAdapterPosition()).getId();
        bundle.putString("walletname", walletName);
        bundle.putInt("walletid", walletID);
        intent.putExtras(bundle);
        mCtx.startActivity(intent);
    }

And the code for the fragments

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

        navView = findViewById(R.id.nav_view);
        addBadgeView();
        AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
                R.id.navigation_home, R.id.navigation_transactions, R.id.navigation_wallets, R.id.navigation_account)
                .build();
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
//        NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
        NavigationUI.setupWithNavController(navView, navController);
    }
Kennedy
  • 547
  • 4
  • 23
  • Show me your code you init WalletFragment? Your activity contains 2 fragments right? – Công Hải May 28 '20 at 09:40
  • i update the whole activity code – Kennedy May 28 '20 at 09:44
  • @Kennedy try initializing the variable `userWalletList` inside of the `loadUserWallets()` method – cgb_pandey May 28 '20 at 09:47
  • @cgb_pandey i get other null pointers, i think the problem is i am creating a new instance of wallet fragment instead of reusing the old instance – Kennedy May 28 '20 at 09:50
  • Dont see your activity code. Just nacigate code. Could you update it? – Công Hải May 28 '20 at 10:00
  • Does this answer your question? [What is a NullPointerException, and how do I fix it?](https://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it) – denvercoder9 May 28 '20 at 10:03
  • @CôngHải i'm sorry i don't quite get the exact code you are asking for – Kennedy May 28 '20 at 10:04
  • 1
    @Kennedy do not call `requireActivity().finish()` after deleting the wallet in the `SettingsFragment`. That will destroy your host activity and everything. Furthermore, you have called `walletsFragment!!.updateWalletFragment()` after finishing your host **Activity**. You can delete the wallets from `SettingsFragment` and then return to `WalletFragment` and let it re-retrieve the data with updated changes. – cgb_pandey May 28 '20 at 10:05
  • @CôngHải i would update the code now i understand, i use nav host – Kennedy May 28 '20 at 10:06
  • @CôngHải updated – Kennedy May 28 '20 at 10:07
  • @cgb_pandey good point thanks, but i also need the activity to dismiss after deleting the wallet – Kennedy May 28 '20 at 10:12
  • @sonnet sadly no, i know what a nullpointer is, i'm just looking for a way to reuse my wallet fragment instance – Kennedy May 28 '20 at 10:14
  • @Kennedy I didn't know you had another activity. Basically, you should have followed `One Activity-Multiple Fragments` pattern – cgb_pandey May 28 '20 at 10:14
  • I have one activity multiple frgments, but one of my fragments needs a settings activity – Kennedy May 28 '20 at 10:17
  • Why do you need a settings activity? If it is because you need a toolbar or custom layout along with original preferencescreen in the SettingsFragment, there is a way to get it without the need of settings activity. – cgb_pandey May 28 '20 at 10:24
  • @cgb_pandey each wallet item in the wallet fragment, needs an individual settings – Kennedy May 28 '20 at 10:28
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/214815/discussion-between-cgb-pandey-and-kennedy). – cgb_pandey May 28 '20 at 10:30

1 Answers1

1

You have no way to get WalletFragment when you in another Activity. Simple solution for your case is you should use method startActivityForResult.

  1. In WalletAdapter pass walletFragment to it, change the constructor of it.
private Fragment mFragment;
WalletAdapter(FragmentManager manager, ArrayList<Wallet> list, Fragment fragment) {
    // your init
    mFragment = fragment;
}

  1. Change method navigate to SettingActivity
 private void showSettingsActivity(RecyclerView.ViewHolder dataObjectHolder){
        Intent intent = new Intent(mCtx , WalletSettings.class);
        Bundle bundle = new Bundle();
        String walletName = userWalletList.get(dataObjectHolder.getAdapterPosition()).getWalletName();
        int walletID = userWalletList.get(dataObjectHolder.getAdapterPosition()).getId();
        bundle.putString("walletname", walletName);
        bundle.putInt("walletid", walletID);
        intent.putExtras(bundle);
        mFragment.startActivityForResult(intent, 123); // you can define request code
    }
  1. In WalletFragment override onActivityResult
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK && requestCode == 123) {
            updateWalletFragment();
        }
    }
  1. In SettingsFragment remove all your code relate to walletFragment and change to this
if (obj.getBoolean("success")) {
                                Toast.makeText(context, obj.getString("message"), Toast.LENGTH_SHORT).show()
                                requireActivity().setResult(Activity.RESULT_OK)
                                requireActivity().finish()
                            }
Công Hải
  • 4,961
  • 3
  • 14
  • 20