Как создать RecyclerView без зависания приложения - PullRequest
0 голосов
/ 08 июля 2020

Перед тем как начать, я должен сказать, что я абсолютный новичок в 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();
}

}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...