使用 AsyncTask 在 Fragment 的 RecyclerView 中显示来自 json 的数据?
Posted
技术标签:
【中文标题】使用 AsyncTask 在 Fragment 的 RecyclerView 中显示来自 json 的数据?【英文标题】:Display data from json in RecyclerView of Fragment using AsyncTask? 【发布时间】:2020-08-21 08:34:59 【问题描述】:我有以下课程:
CategoryFragment.java
public class CategoryFragment extends Fragment
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "category_name";
// TODO: Rename and change types of parameters
private int mParam1;
public CategoryFragment()
// Required empty public constructor
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @return A new instance of fragment CategoryFragment.
*/
// TODO: Rename and change types and number of parameters
public static CategoryFragment newInstance(int param1)
CategoryFragment fragment = new CategoryFragment();
Bundle args = new Bundle();
args.putInt(ARG_PARAM1, param1);
fragment.setArguments(args);
return fragment;
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
if (getArguments() != null)
mParam1 = getArguments().getInt(ARG_PARAM1);
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
Context context = getActivity();
View view = inflater.inflate(R.layout.listado_noticias, container, false);
RecyclerView rw_noticias = view.findViewById(R.id.rw_noticias);
new LoadArticlesTask().execute(MainScreen.mPrefs,MainScreen.hasRemember,view,context,rw_noticias);
return null;
listado_noticias.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:id="@+id/constraintLayout"
xmlns:tools="http://schemas.android.com/tools">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rw_noticias"
android:layout_
android:layout_ />
</androidx.constraintlayout.widget.ConstraintLayout>
加载ArticlesTask.java
public class LoadArticlesTask extends AsyncTask<Object, Void, List<Article>>
private static final String TAG = "LoadArticlesTask";
private View view;
private Context context;
private RecyclerView rw_noticias;
@Override
protected List<Article> doInBackground(Object... params)
SharedPreferences sp = (SharedPreferences)params[0];
boolean hasRemember = (boolean)params[1];
view = (View)params[2];
context = (Context)params[3];
rw_noticias = (RecyclerView)params[4];
List<Article> res = null;
Properties ini = new Properties();
ini.setProperty(RESTConnection.ATTR_SERVICE_URL,Constants.URL_SERVICE);
ini.setProperty(RESTConnection.ATTR_REQUIRE_SELF_CERT,Constants.CERT_VALUE);
ModelManager.configureConnection(ini);
String strIdUser;
String strApiKey;
String strIdAuthUser;
if(hasRemember)
strIdUser = sp.getString("pref_apikey","");
strApiKey = sp.getString("pref_IdUser","");
strIdAuthUser = sp.getString("pref_strIdAuthUser","");
else
strIdUser = ModelManager.getLoggedIdUSer();
strApiKey = ModelManager.getLoggedApiKey();
strIdAuthUser = ModelManager.getLoggedAuthType();
//ModelManager uses singleton pattern, connecting once per app execution in enough
if (!ModelManager.isConnected())
// if it is the first login
if (strIdUser==null || strIdUser.equals(""))
try
ModelManager.login(Constants.USER, Constants.PASS);
catch (AuthenticationError e)
Log.e(TAG, e.getMessage());
// if we have saved user credentials from previous connections
else
ModelManager.stayloggedin(strIdUser,strApiKey,strIdAuthUser);
//If connection has been successful
if (ModelManager.isConnected())
try
// obtain 6 articles from offset 0
res = ModelManager.getArticles(6, 0);
for (Article article : res)
// We print articles in Log
Log.i(TAG, String.valueOf(article));
catch (ServerCommunicationError e)
Log.e(TAG,e.getMessage());
return res;
@Override
protected void onPostExecute(List<Article> articles)
super.onPostExecute(articles);
Log.i("Articles", articles.toString());
for (Article article : articles)
// We print articles in Log
Log.i("Articles", String.valueOf(article));
refreshList(articles,view);
public void refreshList(List<Article> data, View view)
if (data == null)
return;
for (Article article : data)
// We print articles in Log
Log.i("Articles_rl", String.valueOf(article));
final LinearLayoutManager layoutManager = new LinearLayoutManager(context);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
rw_noticias.setLayoutManager(layoutManager);
ArticlesAdapter articlesAdapter = new ArticlesAdapter(data);
rw_noticias.setAdapter(articlesAdapter);
((ArticlesAdapter)rw_noticias.getAdapter()).updateData(data);
ArticlesAdapter.java
public class ArticlesAdapter extends RecyclerView.Adapter<ArticlesAdapter.ArticleViewHolder>
private List<Article> articulos;
public ArticlesAdapter(List<Article> articulos)
this.articulos = articulos;
@NonNull
@Override
public ArticleViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_layout_article, parent, false);
return new ArticleViewHolder(v);
@Override
public void onBindViewHolder(@NonNull ArticleViewHolder holder, int position)
Bitmap imagen = null;
holder.category.setText(articulos.get(position).getCategory());
holder.title.setText(articulos.get(position).getTitleText());
holder.resumen.setText(articulos.get(position).getAbstractText());
try
imagen = SerializationUtils.base64StringToImg(articulos.get(position).getImage().getImage());
catch (ServerCommunicationError serverCommunicationError)
serverCommunicationError.printStackTrace();
holder.thumbnail.setImageBitmap(imagen);
@Override
public int getItemCount()
return articulos.size();
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView)
super.onAttachedToRecyclerView(recyclerView);
public void updateData(List<Article>data)
articulos.clear();
articulos.addAll(data);
notifyDataSetChanged(); //notify to repaint the list
public void articlesFilterCategory(String category)
for (Article a : articulos)
if(!category.equals("ALL") && !a.getCategory().equals(category))
articulos.remove(a);
public static class ArticleViewHolder extends RecyclerView.ViewHolder
CardView cv;
TextView category;
TextView title;
TextView resumen;
ImageView thumbnail;
public ArticleViewHolder(@NonNull View itemView)
super(itemView);
cv = (CardView)itemView.findViewById(R.id.card_article);
category = (TextView)itemView.findViewById(R.id.category_noticia);
resumen = (TextView)itemView.findViewById(R.id.resumen_noticia);
thumbnail = (ImageView)itemView.findViewById(R.id.thumbnail);
card_layout_article.xml
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical" android:layout_
android:layout_
android:foreground="?attr/selectableItemBackground"
android:ellipsize="end"
android:id="@+id/card_article"
>
<RelativeLayout
android:layout_
android:layout_
android:paddingBottom="16dp"
android:paddingHorizontal="1dp">
<ImageView
android:id="@+id/thumbnail"
android:layout_
android:layout_
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="1dp"
android:layout_marginTop="1dp"
android:adjustViewBounds="true"
android:background="@drawable/a15877171854035"
android:cropToPadding="true"
android:scaleType="fitXY"
android:src="@drawable/degradado" />
<View
android:layout_
android:layout_
android:background="@drawable/degradado" />
<TextView
android:id="@+id/title_noticia"
android:layout_
android:layout_
android:layout_alignBottom="@+id/thumbnail"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="107dp"
android:layout_marginEnd="107dp"
android:layout_marginBottom="95dp"
android:text="Nuevo caso de coronavirus"
android:textAlignment="center"
android:textColor="@color/cardview_light_background"
android:textSize="20dp"
android:textStyle="bold" />
<TextView
android:id="@+id/category_noticia"
android:layout_
android:layout_
android:layout_alignBottom="@+id/thumbnail"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="11dp"
android:layout_marginEnd="316dp"
android:layout_marginBottom="145dp"
android:text="NATIONAL"
android:textAlignment="center"
android:textColor="@color/cardview_light_background"
android:textSize="15dp"
android:textStyle="bold" />
<TextView
android:id="@+id/resumen_noticia"
android:layout_
android:layout_
android:layout_alignBottom="@+id/thumbnail"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:layout_marginBottom="-1dp"
android:text="Nuevo caso de coronavirus"
android:textAlignment="viewStart"
android:textColor="@color/cardview_light_background"
android:textSize="11dp"
android:textStyle="bold" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
在我在异步任务的 Post Execute 中拥有的 log.i 中,我可以看到文章是如何形成的(Article 类有一个 toString () 函数)。
但我无法在 RecyclerView 中看到文章。我究竟做错了什么? Capture: Main screen with recyclerView empty...
谢谢!
【问题讨论】:
【参考方案1】:传递RecyclerView
的实例@like -
new LoadArticlesTask().execute(MainScreen.mPrefs, MainScreen.hasRemember, view, rw_noticias, context);
在LoadArticlesTask
上接收此信息,就像在View
上一样。
不要在你的类中重新初始化/使用这个代码 -
RecyclerView rw_noticias = view.findViewById(R.id.rw_noticias);
【讨论】:
谢谢。用您的回复@W4R10CK 更新问题,但仍然无法正常工作...【参考方案2】:在您的card_layout_article.xml
中,将高度wrap_content
设为cardview
:
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical" android:layout_
android:layout_
........
........
同样在您的回收站视图布局中,尝试使用 RelativeLayout
而不是 RelativeLayout
作为父级:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:id="@+id/constraintLayout"
xmlns:tools="http://schemas.android.com/tools">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rw_noticias"
android:layout_
android:layout_ />
</RelativeLayout>
【讨论】:
以上是关于使用 AsyncTask 在 Fragment 的 RecyclerView 中显示来自 json 的数据?的主要内容,如果未能解决你的问题,请参考以下文章
打开新的 Fragment 和 AsyncTask 时显示 ProgressDialog
从 Fragment 内的 AsyncTask 重新启动 Loader (SQLite) 时出现 IllegalStateException