#android #android-fragments #android-volley #bottomnavigationview #android-anr-dialog
#Android #android-фрагменты #android-volley #bottomnavigationview #android-anr-dialog
Вопрос:
Я пытался решить эту проблему в течение двух дней. К сожалению, улучшения минимальны.
Я использую BottomNavigationView, который переключает фрагменты с помощью getSupportFragmentManager().beginTransaction().replace(...
Каждый фрагмент при создании вызывает API с использованием Volley. пример:
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_services, container, false);
....
callAPI();
}
private void callAPI() {
VolleyUtils.makeJsonObjectRequest(context, ..., new VolleyResponseListener() {
@Override
public void onError(String message) {
System.out.println("Error: " message);
}
@Override
public void onResponse(String response) {
//JSON processing
//textView.setText(...);
}
}
}
VolleyUtils.java:
public class VolleyUtils {
public static void makeJsonObjectRequest(Context context, ..., final VolleyResponseListener listener) {
StringRequest jsonObjectRequest = new StringRequest
(Request.Method.POST, "API URL", listener::onResponse, error -> listener.onError(error.toString())) {
@Override
public byte[] getBody() {
//DATA
}
@Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
try {
String jsonString = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
JSONObject responseObj = new JSONObject(jsonString);
jsonString = responseObj.getJSONObject("response").toString();
//System.out.println(jsonString); //TODO remove debug line
return Response.success(jsonString,
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException | JSONException e) {
return Response.error(new ParseError(e));
}
}
};
// Access the RequestQueue through singleton class.
VolleySingleton.getInstance(context).addToRequestQueue(jsonObjectRequest);
}
}
VolleySingleton.java:
public class VolleySingleton {
@SuppressLint("StaticFieldLeak")
private static VolleySingleton instance;
private RequestQueue requestQueue;
@SuppressLint("StaticFieldLeak")
private static Context ctx;
private VolleySingleton(Context context) {
ctx = context;
requestQueue = getRequestQueue();
}
public static synchronized VolleySingleton getInstance(Context context) {
if (instance == null)
instance = new VolleySingleton(context);
return instance;
}
public RequestQueue getRequestQueue() {
if (requestQueue == null)
requestQueue = Volley.newRequestQueue(ctx.getApplicationContext());
return requestQueue;
}
public <T> void addToRequestQueue(Request<T> req) {
getRequestQueue().add(req);
}
}
VolleyResponseListener:
public interface VolleyResponseListener {
void onError(String message);
void onResponse(String response);
}
Проблема в том, что эффект ANR возникает при переключении фрагментов с использованием BottomNavigationView
Лучшие улучшения, которых мне удалось добиться благодаря:
APIRunnable apiRunnable = new APIRunnable();
thread = new Thread(apiRunnable);
thread.start();
...
class APIRunnable implements Runnable {
@Override
public void run() {
callAPI();
}
}
Но при более быстром переключении эффект ANR все равно возникает
I/Choreographer: Skipped 64 frames! The application may be doing too much work on its main thread.
Я действительно больше не знаю, как это решить. Я буду рад любой помощи
Спасибо
Комментарии:
1. Я бы настоятельно рекомендовал перейти на модернизацию из Volley. Вы избавите себя от многих головных болей, которые у вас сейчас возникают
2. @IvanWooll хорошо, дай мне попробовать
3. @IvanWooll это хуже:(
4. @IvanWooll Теперь ANR также происходит в эмуляторе, чего раньше не было
Ответ №1:
Я решил проблему:
Я не понимал, что когда я запрашивал API, я вызывал метод, который генерировал данные POST.
Теперь я вызываю этот метод с new Thread
помощью, а затем вызываю API.
Это решило проблему, и даже при быстром переключении все проходит гладко.
Тем не менее, я также переключился с Volley на модернизацию.
Спасибо Ивану за его помощь