Home > front end >  Fragment not attached to a context; requireContext() in ArrayAdapter, Async Task
Fragment not attached to a context; requireContext() in ArrayAdapter, Async Task

Time:01-30

Can't figure out what I have to do, to create a ListView by using ArrayAdapter. So far here's my code:

class GetSongListAsync(private val activity: LastSongs) : AsyncTask<Void, Void, Array<String>>() {
        override fun doInBackground(vararg params: Void): Array<String> {
            val url =
                URL("https://vivalaresistance.ru/radio/stuff/vlrradiobot.php?type=getPlaylist")
            val connection = url.openConnection() as HttpURLConnection
            connection.requestMethod = "GET"
            connection.connect()

            val songList = BufferedReader(InputStreamReader(connection.inputStream, "windows-1251"))

            connection.disconnect()
            return songList
                .readText()
                .replace("и&#774;", "й")
                .replace("И&#774;", "Й")
                .split("\n").dropLast(1).toTypedArray()
        }

        override fun onPostExecute(result: Array<String>) {
            super.onPostExecute(result)
            val list = LastSongs().view?.findViewById<ListView>(R.id.list)
            val arrayAdapter = ArrayAdapter(activity.requireContext(), android.R.layout.simple_list_item_1, result)
            list?.adapter = arrayAdapter
        }
    }

Right now the app is crashing everytime I'm switching to LastSongs fragment and I'm getting java.lang.IllegalStateException: Fragment LastSongs{79211d9} (2b2b2711-f9a8-4352-92ec-55a25a224ea0) not attached to a context.

If I comment three lines and try to Log the result, everything is fine. The result is exactly what i need.

override fun onPostExecute(result: Array<String>) {
            super.onPostExecute(result)
            Log.d("Songs", result.joinToString("; "))
            // val list = LastSongs().view?.findViewById<ListView>(R.id.list)
            // val arrayAdapter = ArrayAdapter(activity.requireContext(), android.R.layout.simple_list_item_1, result)
            // list?.adapter = arrayAdapter
        }

So far I find, that the problem is with activity.requireContext(). I'm making a mistake that I can't understand. How can I get the right context here?

CodePudding user response:

Looks like your code isn't providing the correct params, if you are using the androidx.fragment.app.Fragment you can simply call requireContext() or requireActivity()

private View view;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
   view = inflater.inflate(R.layout.fragment_page, container, false);
   return view;
}

val list = view?.findViewById<ListView>(R.id.list)
val arrayAdapter = ArrayAdapter(view.getContext(), android.R.layout.simple_list_item_1, counties)```


Please check your imports.

CodePudding user response:

I finally fixed it. I added two parameters to my GetSongListAsync class: one for context and one for list. Now it looks like this:

class GetSongListAsync(private val context: Context, private val list: ListView) : AsyncTask<Void, Void, Array<String>>() {
        override fun doInBackground(vararg params: Void): Array<String> {
            *stuff*
        }

        override fun onPostExecute(result: Array<String>) {
            super.onPostExecute(result)
            val arrayAdapter = ArrayAdapter(context, android.R.layout.simple_list_item_1, result)
            list.adapter = arrayAdapter
        }
    }

Now every time I'm calling this class from view, I have to add this parameters.

    val reqCon = requireContext()
    val swipe: SwipeRefreshLayout = view.findViewById(R.id.swipe)
    val list = view.findViewById<ListView>(R.id.list)

    swipe.setOnRefreshListener {
        GetSongListAsync(reqCon, list).execute()
        swipe.isRefreshing = false
    }

Maybe not the best way to do it, but it works.

  • Related