Android SetText в обратном вызове OkHttp Async, вызывающем сбой

У меня есть активность Android, которая выполняет асинхронный вызов Okhttp, когда активность загружается (вызывается из метода onStart как getActiveRequests()).

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

Button btLogout;
UserLocalStore userLocalStore;
String username;
String userEmail;
String recentAppName;
String recentRequestTime;
String isExpired;
TelephonyManager telephonyManager;
OkHttpClient client;
TextView tvRecentAppName, tvRecentRequestTime, tvIsExpired;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    userLocalStore = new UserLocalStore(this);
    telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

    TextView tvUserName = (TextView) findViewById(R.id.userName);
    TextView tvUserEmail = (TextView) findViewById(R.id.userEmail);

    tvRecentAppName = (TextView) findViewById(R.id.recentAppName);
    tvRecentRequestTime = (TextView) findViewById(R.id.recentRequestTime);
    tvIsExpired = (TextView) findViewById(R.id.isExpired);

    client = new OkHttpClient();
    username = userLocalStore.getLoggedInUser().name;
    userEmail = userLocalStore.getLoggedInUser().email;

    tvUserEmail.setText(userEmail);
    tvUserName.setText(username);

    btLogout = (Button) findViewById(R.id.btLogout);
    btLogout.setOnClickListener(this);
}

@Override
protected void onStart() {
    super.onStart();

    if(authenticateUser() == true){
        getActiveRequests();
    }else{
        startActivity(new Intent(this, LoginActivity.class));
    }
}

Что я хочу сделать, так это обновить пользовательский интерфейс после того, как вызов Http был сделан с использованием методов SetText. Вот мой вызов, реализованный в методе GetActiveRequests().

client.newCall(request)
            .enqueue(new Callback() {

                @Override
                public void onFailure(Call call, IOException e) {
                    String hello = "failed call";
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    final String responseData = response.body().string();

                    if (responseData != null) {
                        Gson gson = new Gson();
                        JsonElement element = gson.fromJson(responseData, JsonElement.class);
                        JsonObject jsonObject = element.getAsJsonObject();
                        final AccessRequest request = gson.fromJson(jsonObject, AccessRequest.class);

                        recentAppName = request.AppName.toString();
                        recentRequestTime = request.RequestTime.toString();
                        if (request.IsExpired)
                            isExpired = "Has Expired";
                        else isExpired = "Active";

                        tvRecentAppName.setText(recentAppName);
                        tvRecentRequestTime.setText(recentRequestTime);
                        tvIsExpired.setText(isExpired);
                    }
                }
            });

Проблема, с которой я сталкиваюсь, заключается в том, что когда отладчик достигает SetText строк кода, это приводит к сбою и закрытию приложения. Я не понимаю, как я могу решить эту проблему, но я предполагаю, что это связано с тем, что вызов Okhttp Async не может обновить пользовательский интерфейс, поскольку мои методы setText отлично работают в onCreate().


person jjharrison    schedule 14.04.2016    source источник
comment
Вероятно, это связано с тем, что результат равен нулю, и вы не можете установить нулевое значение для представления.   -  person Eenvincible    schedule 14.04.2016
comment
См. здесь ответ Джейка Уортона, stackoverflow .com/questions/24246783/   -  person K Neeraj Lal    schedule 14.04.2016
comment
Проверьте мой ответ и попробуйте обновить представления в потоке пользовательского интерфейса.   -  person Rohit Arya    schedule 14.04.2016


Ответы (1)


Это связано с тем, что обновления представлений могут выполняться только в потоке пользовательского интерфейса, а onResponse OkHttp работает в фоновом потоке. Попробуйте запустить это в основном потоке следующим образом:

@Override
public void onResponse(Call call, Response response) throws IOException {
     final String responseData = response.body().string();

     if (responseData != null) {
        Gson gson = new Gson();
        JsonElement element = gson.fromJson(responseData, JsonElement.class);
        JsonObject jsonObject = element.getAsJsonObject();
        final AccessRequest request = gson.fromJson(jsonObject, AccessRequest.class);

        recentAppName = request.AppName.toString();
        recentRequestTime = request.RequestTime.toString();
        if (request.IsExpired)
            isExpired = "Has Expired";
        else isExpired = "Active";

        MainActivity.this.runOnUiThread(new Runnable() {
            @Override
            public void run() {
               //Handle UI here                        
               tvRecentAppName.setText(recentAppName);
               tvRecentRequestTime.setText(recentRequestTime);
               tvIsExpired.setText(isExpired);                
            }
       });
    }
}

Точно так же, если вы обновили какие-либо представления на onFailure, сделайте это в потоке пользовательского интерфейса.

person Rohit Arya    schedule 14.04.2016