-1

I have a function that requests data from an api and fills an array list. Then i use the data from the arraylist in a textView. The problem that occurs is that the function takes time to load the data and the code in which i set the text view gets executed before the arraylist is populated resulting in a crash...I have used Countdown latch to tackle this problem but it isnt working i have used it wrong most probably.

apirequest function

 private void RequestDataFromApi() {

        DotaAPIEndpoints textApiService= API_Client.getClient().create(DotaAPIEndpoints.class);
        Call<List<Heroes>> call2 =textApiService.getHeroes();
        call2.enqueue(new Callback<List<Heroes>>() {
            @Override
            public void onResponse(Call<List<Heroes>> call, Response<List<Heroes>> response) {
                hero_list.clear();
                hero_list.addAll(response.body());

            }

            @Override
            public void onFailure(Call<List<Heroes>> call, Throwable t) {
                Toast.makeText(MainActivity.this, "hero_list call failed!", Toast.LENGTH_SHORT).show();
            }
        });
        requestLatch.countDown();
    }
setText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                try {
                    requestLatch.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                textt.setText(hero_list.get(0).getHeroImg());

            }
        });
Saim Nasser
  • 71
  • 1
  • 6
  • What `count` was the `CountDownLatch` created with? The number of heroes? If so, you need to call `countDown()` once for each hero, so the call should be made from within `onResponse` *and* `onFailure`, otherwise the count will never reach zero. – Andreas Jul 22 '19 at 20:09
  • The `await` call in the `onClick` callback is on ui thread which means you are potentially blocking ui thread which can lead to ANR. Seems much simpler to post result to view in `onResponse` using a looper post (to ui thread): https://stackoverflow.com/a/25250494/2711811 . You will need to the view. –  Jul 22 '19 at 20:22

1 Answers1

1
setText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                try {
                    requestLatch.await();

You cannot call await on the UI thread. Calling await at this point in the above code is telling the UI thread to wait - if the UI thread is waiting, it cannot draw the screen updates, so the system will crash with an Activity Not Responding error.


Perhaps this helps, this is a way to safely allow the button to be clicked and not crash if the data has not loaded yet. (No need for a CountdownLatch at all)

        setText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(hero_list.isEmpty()) {
                    Toast.makeText(MainActivity.this, "List not ready", Toast.LENGTH_SHORT).show();
                    return;
                }
                textt.setText(hero_list.get(0).getHeroImg());
            }
        });
Blundell
  • 75,855
  • 30
  • 208
  • 233