Okhttp3 вызывает сбой приложения при закрытии активности перед загрузкой запроса
Все отлично работает Но я загружаю Фрагмент Вопроса и сразу же щелкаю назад и покидаю приложение, не позволяя завершить запрос. Вылетает приложение. Я попытался осмотреться, но не могу найти решение, которое поможет мне предотвратить сбои. Я прилагаюlogcat
и Questions
класс для справки.
LogCat
12-11 15:37:44.898 16772-16835/com.aftertutor.app E/AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher
Process: com.aftertutor.app, PID: 16772
java.lang.NullPointerException
at com.aftertutor.app.Question$1.onResponse(Question.java:112)
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:153)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
Вопрос класс
package com.aftertutor.app;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.CardView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.aftertutor.app.model.API;
import com.dpizarro.autolabel.library.AutoLabelUI;
import com.dpizarro.autolabel.library.AutoLabelUISettings;
import com.github.thunder413.datetimeutils.DateTimeStyle;
import com.github.thunder413.datetimeutils.DateTimeUtils;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.util.Date;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class Question extends Fragment {
public String id;
public TextView title;
public TextView desc;
public TextView date;
public TextView edit;
public TextView report;
public TextView username;
public AutoLabelUI tags;
public CardView cardView;
public ProgressBar progressBar;
public TextView votes;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_question, null);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
// Equivalent to on Create
super.onViewCreated(view, savedInstanceState);
getActivity().setTitle("Loading...");
title = view.findViewById(R.id.ques_title);
desc = view.findViewById(R.id.ques_desc);
date = view.findViewById(R.id.ques_time);
edit = view.findViewById(R.id.ques_edit);
report = view.findViewById(R.id.ques_report);
username = view.findViewById(R.id.ques_username);
tags = view.findViewById(R.id.ques_labels);
cardView = view.findViewById(R.id.ques_card);
progressBar = view.findViewById(R.id.ques_progress);
votes = view.findViewById(R.id.ques_votes);
Bundle arg = getArguments();
if (arg != null && arg.containsKey("id")) {
id = arg.getString("id");
}
loadQuestion(id);
}
public void loadQuestion(String qid) {
final API api = new API();
OkHttpClient client = new OkHttpClient();
RequestBody body = new FormBody.Builder()
.add("qid", qid)
.build();
Request request = api.call("get_question", body, getContext(), getActivity());
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
call.cancel();
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
MaterialDialog dialog = api.prepareDialog(getContext(), "An Error Occoured", "An Error Occoured. Please make sure you are connected to the internet and try again. If the issue still persists please contact support.");
dialog.show();
}
});
}
@Override
public void onResponse(Call call, Response response) throws IOException {
final String responseText = response.body().string();
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
try {
JSONObject jsonObject = new JSONObject(responseText);
if (jsonObject.get("status").equals("ok"))
{
JSONObject payload = jsonObject.getJSONObject("payload");
JSONObject questionItem = payload.getJSONObject("question");
title.setText(questionItem.get("title").toString());
getActivity().setTitle(questionItem.get("title").toString());
desc.setText(questionItem.get("description").toString());
date.setText(DateTimeUtils.getTimeAgo(getContext(), new Date(questionItem.getInt("postedOn") * 1000L), DateTimeStyle.AGO_FULL_STRING));
votes.setText(questionItem.getInt("votes") + "");
username.setText("@" + questionItem.get("postedBy").toString());
String[] taggs = api.toStringArray(questionItem.getJSONArray("tags"));
edit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Edit Page here
}
});
report.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MaterialDialog dialog = new MaterialDialog.Builder(getContext())
.title("Report this question because...")
.items(R.array.report_array)
.itemsCallbackSingleChoice(0, new MaterialDialog.ListCallbackSingleChoice() {
@Override
public boolean onSelection(MaterialDialog dialog, View itemView, int which, CharSequence text) {
Toast.makeText(getContext(), "YOU SELECTED: " + which, Toast.LENGTH_SHORT).show();
return false;
}
})
.content("Reporting will let us know that something isn't wrong with this post. We will take action asap.")
.positiveText("Report")
.onPositive(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
Toast.makeText(getContext(), "Reported", Toast.LENGTH_SHORT).show();
}
})
.negativeText("Cancel")
.build();
dialog.show();
}
});
AutoLabelUISettings autoLabelUISettings = new AutoLabelUISettings.Builder()
.withMaxLabels(5)
.withShowCross(false)
.withLabelsClickables(false)
.withBackgroundResource(R.drawable.rounded_corner)
.withTextSize(R.dimen.custom_label_font_size)
.withLabelPadding(R.dimen.custom_label_font_padding)
.build();
tags.setSettings(autoLabelUISettings);
tags.clear();
for (String tag: taggs) {
tags.addLabel(tag);
}
progressBar.setVisibility(View.GONE);
cardView.setVisibility(View.VISIBLE);
}
else if (jsonObject.get("status").equals("error"))
{
MaterialDialog dialog = api.prepareDialog(getContext(), jsonObject.getJSONObject("dialog").get("title").toString(), jsonObject.getJSONObject("dialog").get("message").toString());
dialog.show();
}
else
{
MaterialDialog dialog = api.prepareDialog(getContext(), "An Error Occurred", "An Error Occurred. Please make sure you are connected to the internet and try again. If the issue still persists please contact support.");
dialog.show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
});
}
}
2 ответа
Решение
Вы должны отменить звонок в onPause()
так что звоните как поле:
private Call call;
а потом поменяй loadQuestion()
метод для:
call = client.newCall(request);
call.enqueue(new Callback() {
И отменить запрос:
@Override
public void onPause() {
super.onPause();
if (call != null){
call.cancel();
}
}
Поскольку вы уверены, что ответ на запрос вылетает приложение (Exception
) если Fragment
пауза, то в качестве альтернативы вы можете объявить boolean
в вашем классе, как:
private boolean active= true;
Тогда в вашем onResume
:
@Override
public void onResume() {
super.onResume();
active= true;
}
Тогда в вашем onPause
@Override
public void onPause() {
super.onPause();
active= false;
}
Тогда в вызове вашего фрагмента onResponse
добавить if
заявление:
@Override
public void onResponse(Call call, Response response) throws IOException {
if(active){
//Call your extra code here!
}
}