-4
   override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_main, container, false)
        setHasOptionsMenu(true)
        search_bar = view.findViewById(R.id.main_search_bar)
        refresh = view.findViewById(R.id.main_frg_swipe_refresh)
        search_bar.setHint("Search Restaurants")
        no_net = view.findViewById(R.id.main_frg_no_net)
        appbar = view.findViewById(R.id.main_frg_appbar)
        progress_bar = view.findViewById(R.id.frg_main_prgs)
        nav_view = requireActivity().findViewById(R.id.main_navigation_view) as NavigationView
        nav_view.setCheckedItem(R.id.home_select)
        recl_view = view.findViewById(R.id.frg_main_rec_view)
        if(Connection().checkConnectivity(activity as Context)) {
            no_net.visibility = View.GONE
            appbar.visibility = View.VISIBLE
            val q = Volley.newRequestQueue(activity as Context)
            val url = "http://13.235.250.119/v2/restaurants/fetch_result/"
            try{
                progress_bar.visibility = View.VISIBLE
                val jsonreq = object : JsonObjectRequest(
                    Request.Method.GET,url,null,
                    Response.Listener {
                        if(it.getJSONObject("data").getBoolean("success")){
                            list = arrayListOf<DataList>()
                            val data = it.getJSONObject("data").getJSONArray("data")
                            for(i in 0 until data.length()){
                                list.add(
                                    DataList(
                                        data.getJSONObject(i).getString("id"),
                                        data.getJSONObject(i).getString("name"),
                                        data.getJSONObject(i).getString("rating"),
                                        data.getJSONObject(i).getString("cost_for_one"),
                                        data.getJSONObject(i).getString("image_url")
                                    )
                                )
                            }
                            recl_view.layoutManager = LinearLayoutManager(activity)
                            recl_view.adapter = MainAdapter(activity as Context,list)
                            progress_bar.visibility = View.GONE
                        }
                    },
                    Response.ErrorListener {
                        appbar.visibility = View.GONE
                        progress_bar.visibility = View.GONE
                        Toast.makeText(activity as Context,"Please Try Again Later.", Toast.LENGTH_SHORT).show()
                    }){
                    override fun getHeaders(): MutableMap<String, String> {
                        val headers = HashMap<String, String>()
                        headers["Content-type"] = "application/json"
                        headers["token"] = "c3acf1e14c21f9"
                        return headers
                    }
                }
                q.add(jsonreq)
            }catch (e: Exception){
                appbar.visibility = View.GONE
                progress_bar.visibility = View.GONE
                Toast.makeText(activity as Context,"Please Try Again Later.", Toast.LENGTH_SHORT).show()
            }
        }
        else{
            appbar.visibility = View.GONE
            Toast.makeText(activity as Context,"Please Check your Internet Connection", Toast.LENGTH_SHORT).show()
            no_net.visibility = View.VISIBLE
        }
        search_bar.addTextChangedListener(object :TextWatcher{
            override fun afterTextChanged(p0: Editable?) {
            }
            override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
            }
            override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {

                val listData = arrayListOf<DataList>()
                for (i in 0 until list.size) {
                    if (list[i].name.toLowerCase()
                            .contains(search_bar.text.toString().toLowerCase()) ||
                        list[i].cost_for_one.contains(search_bar.text.toString()) ||
                        list[i].rating.contains(search_bar.text.toString())
                    ) {
                        listData.add(list[i])
                    }
                }
                recl_view.adapter = MainAdapter(activity as Context, listData)
                (recl_view.adapter as MainAdapter).notifyDataSetChanged()
            }

The error shows at the second line of this code. And the error is.

java.lang.NullPointerException: null cannot be cast to non-null type android.content.Context at com.example.foodly.fragments.MainFragment.onCreateView$lambda-0(MainFragment.kt:81) at com.example.foodly.fragments.MainFragment.lambda$Vf2l8k3CIcfDZee0QEFEEctabhA(Unknown Source:0) at com.example.foodly.fragments.-$$Lambda$MainFragment$Vf2l8k3CIcfDZee0QEFEEctabhA.onResponse(Unknown Source:4) at com.android.volley.toolbox.JsonRequest.deliverResponse(JsonRequest.java:90) at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:102) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:246) at android.app.ActivityThread.main(ActivityThread.java:8512) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)

a_local_nobody
  • 7,947
  • 5
  • 29
  • 51
yazhini
  • 57
  • 1
  • 6

2 Answers2

0

I don't think the issue is because you switched to the dark mode; it's probably list is null since you're getting a NullPointerException. I would check if data is null.

0

You're casting the nullable Activity to a non-null Context in a listener that might be called when the Fragment it no longer attached to an Activity, which means the Activity would be null at that point.

You should generally avoid casting with as. In this case, it masks what the problem was. At least if you used !! to assert the Activity is not null, the stack trace would give you a more detailed explanation of what you did wrong.

Typically, you should use requireActivity() or requireContext() when you need to pass a non-null Context or Activity to something. They will give you the best error message when you use them where you shouldn't. You should be aware of the Fragment lifecycle when you do this and know that it is not safe to get the non-null Activity during stages of the Fragment lifecycle where it might be detached.

(Incidentally, the LinearLayoutManager needs a non-null Activity as well, but it's not annotated to require it, so the compiler let you get away with passing it a nullable activity. Its simpler to set it in the XML anyway.)

Since this is in an asynchronous response, you cannot predict whether the listener will be called while the Fragment is attached or not, so it is not safe to assume a non-null Activity. You should exit the function early if the Activity is null, since at this point there is no more UI to show the data anyway. Something like this:

Response.Listener {
    val attachedContext = activity ?: return@Listener

    // ...
    recl_view.adapter = MainAdapter(attachedContext, list)
    //...
}

It would be better to set up your request in a ViewModel so your current request isn't wasted and rerun redundantly every time the screen rotates or dark mode is toggled. You are also temporarily leaking copies of your Fragment every time this happens because you don't cancel the request when detached.

Tenfour04
  • 83,111
  • 11
  • 94
  • 154