如何在AsyncTask中将Jsoup获取的数据设置到RecyclerView
如何通过AsyncTask将Jsoup获取的数据绑定到RecyclerView
首先,你不用非要把MyAsyncTask改成公共类,把它作为MainActivity的内部类会更方便——这样它可以直接访问Activity中的RecyclerView实例和适配器对象,省去很多回调逻辑的麻烦。下面结合你提到的几个文件,一步步拆解实现方案:
1. 先确认基础数据结构与适配器
确保你的ListItem类已经定义好存储标题的字段:
public class ListItem { private String title; public ListItem(String title) { this.title = title; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } }
MyRecViewAdapter需要提供更新数据的方法,方便后续异步任务完成后刷新列表:
public class MyRecViewAdapter extends RecyclerView.Adapter<MyRecViewAdapter.ViewHolder> { private List<ListItem> itemList; public MyRecViewAdapter(List<ListItem> itemList) { this.itemList = itemList; } // 用于更新数据的核心方法 public void updateData(List<ListItem> newList) { itemList.clear(); itemList.addAll(newList); notifyDataSetChanged(); } // 以下是常规ViewHolder与重写方法,按你的布局实现即可 public static class ViewHolder extends RecyclerView.ViewHolder { TextView titleTv; public ViewHolder(View itemView) { super(itemView); titleTv = itemView.findViewById(R.id.title_textview); } } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.list_item_layout, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(ViewHolder holder, int position) { holder.titleTv.setText(itemList.get(position).getTitle()); } @Override public int getItemCount() { return itemList.size(); } }
2. 在MainActivity中实现内部类AsyncTask
在MainActivity里初始化RecyclerView后,编写内部类MyAsyncTask执行Jsoup解析,解析完成后直接调用适配器的更新方法:
public class MainActivity extends AppCompatActivity { private RecyclerView recyclerView; private MyRecViewAdapter adapter; private List<ListItem> itemList = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 初始化RecyclerView recyclerView = findViewById(R.id.recycler_view); recyclerView.setLayoutManager(new LinearLayoutManager(this)); adapter = new MyRecViewAdapter(itemList); recyclerView.setAdapter(adapter); // 启动异步任务解析网页标题 new MyAsyncTask().execute("你的目标网页URL"); } // 内部类AsyncTask,泛型参数分别对应:输入参数类型、进度更新类型、返回结果类型 private class MyAsyncTask extends AsyncTask<String, Void, List<ListItem>> { @Override protected List<ListItem> doInBackground(String... urls) { List<ListItem> resultList = new ArrayList<>(); String targetUrl = urls[0]; try { // Jsoup网络请求必须在子线程执行(doInBackground) Document doc = Jsoup.connect(targetUrl).get(); // 这里根据你要抓取的标题选择器调整,比如抓取所有h2标签的文本 Elements titleElements = doc.select("h2"); for (Element element : titleElements) { resultList.add(new ListItem(element.text())); } } catch (IOException e) { e.printStackTrace(); } return resultList; } @Override protected void onPostExecute(List<ListItem> resultList) { super.onPostExecute(resultList); // 解析完成后,在主线程更新适配器数据 adapter.updateData(resultList); } } }
3. 关于是否将AsyncTask改为公共类的问题
如果你的异步解析逻辑需要在多个Activity中复用,改成公共类是可行的,但此时需要通过接口回调传递数据(因为公共类无法直接访问Activity的成员)。举个简单的实现例子:
首先定义回调接口:
public interface OnDataLoadedListener { void onDataLoaded(List<ListItem> data); }
然后编写公共类AsyncTask:
public class MyAsyncTask extends AsyncTask<String, Void, List<ListItem>> { private OnDataLoadedListener listener; public MyAsyncTask(OnDataLoadedListener listener) { this.listener = listener; } @Override protected List<ListItem> doInBackground(String... urls) { // 解析逻辑和之前一致,省略 } @Override protected void onPostExecute(List<ListItem> resultList) { super.onPostExecute(resultList); if (listener != null) { listener.onDataLoaded(resultList); } } }
最后在MainActivity中调用:
new MyAsyncTask(new OnDataLoadedListener() { @Override public void onDataLoaded(List<ListItem> data) { adapter.updateData(data); } }).execute("你的目标网页URL");
但如果只是在当前MainActivity中使用,内部类的方式会更简洁,不需要额外的回调逻辑。
必加注意事项
- 别忘了在
AndroidManifest.xml中添加网络权限:<uses-permission android:name="android.permission.INTERNET" /> - 若目标网站是HTTP协议(非HTTPS),Android 11及以上需要在
application标签中添加android:usesCleartextTraffic="true"允许明文流量
内容的提问来源于stack exchange,提问作者Сергей
相关产品推荐
相关产品推荐

