Search code examples
androidmultithreadingriot-games-api

Modifying textviews reliant on threaded API calls?


public View getView(int position, View convertView, ViewGroup parent) {
    LayoutInflater inflater = LayoutInflater.from(getContext());
    View theView = inflater.inflate(R.layout.match_layout, parent, false);
     matchID = getItem(position);

    TextView championName = (TextView) theView.findViewById(R.id.championNameText);
    new Thread(
            new Runnable() {
                public void run() {
                    selectedMatch = RiotAPI.getMatch(matchID);
                    Log.i(TAG, String.valueOf(selectedMatch)); // <-- returns the matches properly
                }
            }).start();

        championName.setText(String.valueOf(selectedMatch.getDuration()));


   // Log.i(TAG, String.valueOf(selectedMatch));  <-- returns nulls
    return theView;
}

I've been running into problem after problem trying to make my first app. My understanding is that I'm not allowed to do api calls in the main thread, so I tried using a seperate thread. The problem is, it takes a few seconds for the API to return data, so selectedMatch is null when I try to update my text view, giving me null pointer exceptions. What is the proper way to handle this?

EDIT: The only workaround I've found so far is putting a empty while loop waiting for the thread to finish first, but this seems very inefficient. Would appreciate more input.

    public View getView(int position, View convertView, ViewGroup parent) {
    LayoutInflater inflater = LayoutInflater.from(getContext());
    View theView = inflater.inflate(R.layout.match_layout, parent, false);
     matchID = getItem(position);

    TextView championName = (TextView) theView.findViewById(R.id.championNameText);
    new Thread(
            new Runnable() {
                public void run() {
                    selectedMatch = RiotAPI.getMatch(matchID);
                    Log.i(TAG, String.valueOf(selectedMatch)); // <-- returns the matches properly
                }
            }).start();
     while (selectedMatch == null)
             {
             }
        championName.setText(String.valueOf(selectedMatch.getDuration()));


   // Log.i(TAG, String.valueOf(selectedMatch));  <-- returns nulls
    return theView;
}

Solution

  • Try using runOnUiThread():

    new Thread(
            new Runnable() {
                public void run() {
                    selectedMatch = RiotAPI.getMatch(matchID);
                    ((YourActivity)getContext()).runOnUiThread(new Runnable(){
    
                   public void run(){
                       championName.setText(String.valueOf(selectedMatch.getDuration()));
                   }
    
             });
    
            }
         }).start();