Перед тем как начать, я должен сказать, что я абсолютный новичок в Android разработке, поэтому мне нужна помощь не только в решении проблемы, но и в понимании того, как все работает на самом деле.
Итак, я создаю приложение, которое предоставляет мне живые обновления случаев Covid-19 в моей стране (Индии) и во всем мире. Мое приложение имеет 1 основное действие и 2 фрагмента.
фрагмент 1
фрагмент 2
Оба этих фрагмента содержат RecyclerView . RecyclerView во фрагменте 1 относительно меньше (содержит около 35 элементов), но RecyclerView во фрагменте 2 содержит список из примерно 200 стран.
Когда я запускаю свое приложение, я хочу, чтобы оба этих RecyclerView были загружены.
Задача проста: вызвать API-> Разобрать JSON -> Обновить адаптер-> Установить адаптер в RecyclerView.
Проблема: пользовательский интерфейс приложения зависает (примерно на 10 секунд), когда я запускаю приложение.
Я искал в Stack Overflow и на Youtube, и до сих пор я создал MyASyncTask, который вызывает API (для фрагмента 2) в фоновом режиме и обновляет RecyclerView.
class MyAsyncTask extends AsyncTask<Void, Example_Item, Void> {
private ArrayList<Example_Item> ExampleList;//Represents the list of data of the Recycler View
private RecyclerView mRecyclerView;
private ExampleAdapter mAdapter;
private Context mContext;
private View RootView;
private String URL;
public MyAsyncTask(Context context, View v,RecyclerView rv,String url,ArrayList<Example_Item> arrayList) {
mContext = context;
RootView=v;
mRecyclerView =rv;
URL=url;
ExampleList=arrayList;
}
@Override
protected void onPreExecute() {
mAdapter=new ExampleAdapter(ExampleList);
mRecyclerView.setAdapter(mAdapter);
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
}
@Override
protected void onProgressUpdate(Example_Item... values) {
ExampleList.add(values[0]);
mAdapter.notifyDataSetChanged();
}
@Override
protected Void doInBackground(Void... voids) {
HttpsTrustManager.allowAllSSL();
RequestQueue requestQueue = Volley.newRequestQueue(mContext);
JsonArrayRequest arrayRequest = new JsonArrayRequest(
Request.Method.GET,
URL,
null,
new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) {
Log.d("Covid", "SUCCESS! JSON: " + response.toString());
CovidData_Countries covidData = CovidData_Countries.fromJSON(response);
if(covidData!=null) {
int len = covidData.arr.length;
for (int i = 0; i < len ; i++) {
publishProgress(covidData.arr[i]);
}
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e("Covid", "Fail " + error.toString());
Toast.makeText(RootView.getContext(), "Request Failed", Toast.LENGTH_SHORT).show();
}
}
);
requestQueue.add(arrayRequest);
return null;
}
Некоторые примечания к приведенному выше коду:
Example_Item - это класс, который представляет каждый элемент списка RecyclerView. CovidData_Countries - это класс, который анализирует JSON. Он имеет член данных publi c arr [] (типа Example_Item), в котором хранятся все объекты Items, которые попадают в RecyclerView.
Что я хочу, чтобы мое приложение работало Примерно: Когда я открываю свое приложение, RecyclerView Fragment 1 сразу загружается (что на самом деле и происходит, это занимает около 0,5 секунды), и я хочу, чтобы RecyclerView во фрагменте 2 загружался постепенно (без зависания пользовательского интерфейса приложения. вверх). Под «постепенно» я имею в виду постатейно, если сложно загрузить все сразу.
Я подумал, что после добавления класса MyAsyncTask пользовательский интерфейс приложения не зависнет, но зависнет.
Может случиться так, что моя MyAsyncTask полностью неверна. В этом случае было бы очень полезно, если бы вы могли показать мне правильный способ реализации в фоновом режиме.
Мой код адаптера:
package com.app.learning.covid_19;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
public class ExampleAdapter extends
RecyclerView.Adapter<ExampleAdapter.ExampleViewHolder>
{
private ArrayList<Example_Item> mExample_items;
public static class ExampleViewHolder extends RecyclerView.ViewHolder{
public TextView mState;//Represents States of India(for Fragment 1) or Country Name(Fragment 2)
public TextView mConfirmed;//Total Confirmed Cases
public TextView mRecovered;//Total Recovered Cases
public TextView mDeceased;//Total Deaths
public TextView mdConfirmed;//Delta Confirmed Cases(New Cases)
public TextView mdRecovered;//Delta Recovered Cases(New Recoveries)
public TextView mdDeceased;//Delta Deaths Cases(New Deaths)
public ExampleViewHolder(View itemView)
{
super(itemView);
mState=itemView.findViewById(R.id.state);
mConfirmed=itemView.findViewById(R.id.confirm);
mRecovered=itemView.findViewById(R.id.recover);
mDeceased=itemView.findViewById(R.id.decease);
mdConfirmed=itemView.findViewById(R.id.dconfirm);
mdRecovered=itemView.findViewById(R.id.drecover);
mdDeceased=itemView.findViewById(R.id.ddecease);
}
}
public ExampleAdapter(ArrayList<Example_Item> RowList){
mExample_items=RowList;
}
@NonNull
@Override
public ExampleViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v= LayoutInflater.from(parent.getContext()).inflate(R.layout.row,parent,false);
ExampleViewHolder evh=new ExampleViewHolder(v);
return evh;
}
@Override
public void onBindViewHolder(@NonNull ExampleViewHolder holder, int position) {
Example_Item currenItem=mExample_items.get(position);
holder.mState.setText(currenItem.getState());
holder.mConfirmed.setText(currenItem.getConf());
holder.mRecovered.setText(currenItem.getRec());
holder.mDeceased.setText(currenItem.getDec());
holder.mdConfirmed.setText(currenItem.getDconf());
holder.mdRecovered.setText(currenItem.getDrec());
holder.mdDeceased.setText(currenItem.getDdec());
}
@Override
public int getItemCount() {
return mExample_items.size();
}
}