OkHttp中的Android SetText异步回调导致崩溃

时间:2016-04-14 16:54:19

标签: java android android-asynctask settext

我有一个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));
    }
}

我想要做的是使用SetText方法进行Http调用后更新UI。这是我的调用,在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调用无法更新UI有关,因为我的setText方法在onCreate()中工作正常。 / p>

1 个答案:

答案 0 :(得分:2)

那是因为观点'更新只能在UI线程上完成,而OkHttp的onResponse在后​​台线程上运行。尝试在主线程上运行,如下所示:

@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上的任何视图,请在UI线程上执行。