Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Android

vicente lee
vicente lee
6,271 Points

Does Call have a join method?

So I've spent nearly two hours trying to figure out how to make the main thread call a thread.join() on a worker:

mGetChartButton.setOnClickListener(new View.OnClickListener() {
    @Override
        public void onClick(View v) {
            String companyName = mSymbolValue.getText().toString();
            getRequest(companyName, "chart");    
            Log.i(TAG, mChartProfile.getSizeDates()+""); // Null exception happens here
    }
}); 

Here's a snippet of getRequest()

OkHttpClient client = new OkHttpClient();
    Request request = new Request
            .Builder()
            .url(completeUrl)
            .build();
    Call call = client.newCall(request);
    call.enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
        }
        @Override
        public void onResponse(Call call, Response response) throws IOException {
            try {
                String jsonData = response.body().string();
                Log.v(TAG, jsonData);
                if (response.isSuccessful()) {
                    if (requestType.equals("quote")) {
                        isValidSearch = getQuote(jsonData);
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                if (isValidSearch) {
                                    updateDisplay();
                                }
                                toggleFacts(isValidSearch);
                            }
                        });
                    }

                    else{
                        getChartInfo(jsonData);
                    }
                } else {
                    alertUserAboutError();
                }
            } catch (IOException e) {
                Log.e(TAG, "Exception caught: ", e);
            } catch (JSONException e) {
                Log.e(TAG, "JSONException caught: ", e);
                Toast.makeText(BuyActivity.this, "oops!", Toast.LENGTH_LONG).show();
            }
        }
    });

And here is a snippet of getChartInfo():

private void getChartInfo(String jsonData) throws JSONException{

    JSONObject wholeChartData = new JSONObject(jsonData);

    JSONArray dates = wholeChartData.getJSONArray("Dates");
    mChartProfile = new ChartProfile();
    // ChartProfile contains ArrayList of ChartDate and ArrayList of ChartValue
    for (int i = 0; i < dates.length(); i++){
        ChartDate chartDate = new ChartDate(dates.getString(i));
        mChartProfile.addToDates(chartDate);
    }
    JSONArray values = close.getJSONArray("values");

    for (int i = 0; i < values.length(); i++){
        ChartValue chartValue = new ChartValue(values.getDouble(i));
        mChartProfile.addToValues(chartValue);
    }
}

So here's the problem, I'm getting a null exception because the main thread finishes way before the worker thread. Meaning the worker thread has not had time to initialize and set the mChartProfile's member variables, and the main thread has already returned from the getRequest() method. So the next thing that the main thread runs is it tries to get the length of an empty ChartProfile and hence the big fat null exception. Does anybody know how to fix this? If only I had a thread.join() like in C++. If Call does not have this functionality, what's another way?

1 Answer

Seth Kroger
Seth Kroger
56,413 Points

Perhaps it's best to step back and ask, what are you trying to accomplish here? If it's logging the data you get from the request, then perhaps doing it in onResponse() after the data comes in is the better choice, with runOnUiThread() amounting to thread.join(). Because Call is making a web request that can take an indeterminate amount of time, you should think of it more like a listener callback much like the OnClickListener waits an indeterminate amount of time for the user to tap something. Just as you start up an app by attaching a listener in onCreate() and exit, waiting for the user to tap the button, you're making a web request and exit, waiting for the server's response.