Android:使用 Asynctask 时 Recyclerview 出现问题

Posted

技术标签:

【中文标题】Android:使用 Asynctask 时 Recyclerview 出现问题【英文标题】:Android: problem with Recyclerview when using Asynctask 【发布时间】:2020-02-02 23:55:50 【问题描述】:

我可以在 Asynctask 中使用 Json 从 API 获取数据,但问题是当我使用 Recyclerview 时。我得到空指针异常错误。请问谁能帮帮我?

                              ***MainActivity.java***
private List<Certifications> mCertifications = new ArrayList<>(); 

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    recyclerView = (RecyclerView) findViewById(R.id.certificationRecyclerview);
    new fetchData().execute();
    recyclerView.setLayoutManager(new LinearLayoutManager(this));

    mAdapter = new GreenAdapter(mCertifications);
    recyclerView.setAdapter(mAdapter);
    



                          ***GreenAdapter.java***  

public class GreenAdapter extends RecycrView.Adapter<GreenAdapter.ViewHolder>
private Context mContext;
private List<Certifications> mCertifications;

public GreenAdapter(List<Certifications> certifications) 
    this.mCertifications = certifications;

/** Inner class */

// Stores and recycles views as they are scrolled off  screen

public static class ViewHolder extends RecyclerView.ViewHolder 
    private TextView certificationTextview;
    private TextView meaningTextview;
    private TextView orderTextview;
    public ViewHolder(@NonNull View itemView) 
        super(itemView);
        certificationTextview = (TextView) itemView.findViewById(R.id.certificationInfo);
        meaningTextview= (TextView) itemView.findViewById(R.id.meaning);
        orderTextview = (TextView) itemView.findViewById(R.id.order);

    

// Methods
// Usually involves inflating a layout from XML and returning the holder
//Create New Views
@NonNull
@Override

public GreenAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) 
    Context context = parent.getContext();
    LayoutInflater inflater = LayoutInflater.from(context);
    View certificationView =  inflater.inflate(R.layout.certification_list,
            parent, false);
    //Return a new holder instance
    final ViewHolder certificationViewHolder = new ViewHolder(certificationView);
    return certificationViewHolder;

//binds the data to the Textview in each row
// Involves populatind data into the item through holder
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) 
    // get the data model based on position
    Certifications certific = mCertifications.get(position);
    //set itemviews based on your views and data model
    holder.certificationTextview.setText(certific.getCertification());
    holder.meaningTextview.setText(certific.getMeaning());
    holder.orderTextview.setText(certific.getOrder());


@Override
public int getItemCount() 
    return mCertifications.size();


**I copied the following from other post**

public void clear()
    mCertifications.clear();
    notifyDataSetChanged();

public void addAll(List<Certifications> list)
    mCertifications.addAll(list);
    notifyDataSetChanged();
  





                             ***Certifications.java***
public class Certifications 
private String mCertification;
private String mMeaning;
private int mOrder; 

public Certifications(String certification,String meaning, int order) 
    mCertification = certification;
    mMeaning = meaning;
    mOrder = order;
    public String getCertification()
    return mCertification;

public String getMeaning()
    return mMeaning;

public int getOrder()
    return mOrder;
 

                          ***FetchData.java*** 

Public class fetchData extends AsyncTask&lt;String,Void, List&lt;Certifications&gt;&gt;

 private GreenAdapter mGreenAdapter;
// Create an empty ArrayList that we can start adding Certifications to    
List<Certifications> mCertifications = new ArrayList<>();;


protected List<Certifications> doInBackground(String... voids) 

   try 

       URL url = new URL("API");
       HttpsURLConnection httpsURLConnection= (HttpsURLConnection) url.openConnection();
       InputStream inputStream=httpsURLConnection.getInputStream();
       BufferedReader bufferedReader= new BufferedReader(new InputStreamReader(inputStream));
       String line = "";
       while (line!=null)
           line = bufferedReader.readLine();
           data = data + line;
       
         // Create a JASONObject from the JSON_RESPONSE string
        JSONObject root = new JSONObject(data);

       JSONObject jsonObject = root.getJSONObject("certifications");

//提取与名为“US”的键关联的JSONArray //代表美国认证列表

       JSONArray jsonArray= jsonObject.getJSONArray("US");


       for (int i=0; i<jsonArray.length();i++)
           JSONObject jasonObject=(JSONObject) jsonArray.get(i);

           String  cert = jasonObject.getString("certification");
           String meaning =jasonObject.getString("meaning");
           int order = jasonObject.getInt("order");

           Certifications certification = new Certifications(cert, meaning, order);
           mCertifications.add(certification);
       


  **Catch code here**

    return mCertifications; **Data**



@Override
protected void onPostExecute(final List<Certifications> dataParsed) 

//运行调试时以下代码出现空指针异常

// 第一次尝试。结果:NullPointerException

    mGreenAdapter.clear();
    mGreenAdapter.addAll(dataParsed);

// 第二次尝试。结果:NullPointerException

    mGreenAdapter = new GreenAdapter( dataParsed);
    mRecyclerView.setAdapter(mGreenAdapter);

   // onPostExecute parenthesis
// fetchData.java

【问题讨论】:

你可能想看看使用 Retrofit 而不是 AsyncTask 来处理 http 请求和解析 Json 现在我必须使用 AsyncTask,然后我会切换到 Retrofit 【参考方案1】:

打电话

new fetchData().execute();

设置适配器后。你的 onCreate 方法看起来像

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    recyclerView = (RecyclerView) findViewById(R.id.certificationRecyclerview);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));

    mAdapter = new GreenAdapter(mCertifications);
    recyclerView.setAdapter(mAdapter);
    new fetchData().execute();
    


【讨论】:

我尝试了您的代码,但仍然无法正常工作。我还尝试使用硬编码数据而不是 HTTP 请求,但我只能看到一行数据。【参考方案2】:

问题是在使用 JSON 获取 Asynctask 中的数据时,我无法将数据填充到 RecyclerView。 如果我为 AsyncTask 创建一个新类,我必须在 MainAcitivity.java 中声明 AsyncTask,否则为 NullPointerException。 我在适配器类中声明了一个方法

public void setData(List<Certifications> data)
//List<Certifications> mCertification;
 mCertifications = data;
 notifyDataSetChanged();

我也关注 Viswanath Kumar Sandu 的帖子,这是我的 MainActivity.java

public class MainActivity extends AppCompatActivity 

private RecyclerView recyclerView;

private GreenAdapter mGreenAdapter;
private List<Certifications> mCertifications = new ArrayList<>();;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    recyclerView =  findViewById(R.id.certificationRecyclerview);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    recyclerView.setHasFixedSize(true);

    mGreenAdapter = new GreenAdapter();
    recyclerView.setAdapter(mGreenAdapter);

    new fetchData().execute();


public class fetchData extends AsyncTask<String,Void, List<Certifications>> 

    String data = "";
    String dataParsed = "";
    String singlePass = "";
    protected List<Certifications> doInBackground(String... voids) 

    try 

          URL url = new URL("https: api);
          HttpsURLConnection httpsURLConnection = (HttpsURLConnection) 
          url.openConnection();
          InputStream inputStream = httpsURLConnection.getInputStream();
          BufferedReader bufferedReader = new BufferedReader(new 
          InputStreamReader(inputStream));
          String line = "";
          while (line != null) 
                line = bufferedReader.readLine();
                data = data + line;
          

          JSONObject root = new JSONObject(data);
          JSONObject jsonObject = root.getJSONObject("certifications");

          JSONArray jsonArray = jsonObject.getJSONArray("US");

          for (int i = 0; i < jsonArray.length(); i++) 
           JSONObject jasonObject = (JSONObject) jsonArray.get(i);
           String cert = jasonObject.getString("certification");
           String meaning = jasonObject.getString("meaning");
           int order = jasonObject.getInt("order");

           Certifications certification = new Certifications(cert, meaning, order);
           mCertifications.add(certification);
          
          jsonArray = jsonObject.getJSONArray("CA");
          for (int i = 0; i < jsonArray.length(); i++) 
          JSONObject jasonObject = (JSONObject) jsonArray.get(i);
          String cert = jasonObject.getString("certification");
          String meaning = jasonObject.getString("meaning");
          int order = jasonObject.getInt("order");
          Certifications certification = new Certifications(cert, meaning,order);
          mCertifications.add(certification);
            
         catch (MalformedURLException e) 
            e.printStackTrace();
         catch (IOException e) 
            e.printStackTrace();

         catch (JSONException e) 
            e.printStackTrace();
        
        return mCertifications;
    
    @Override
    protected void onPostExecute(final List<Certifications> dataParsed) 

    mGreenAdapter.setData(dataParsed);

     //onPostExecute
  // AsyncTask

//MainActivity

【讨论】:

以上是关于Android:使用 Asynctask 时 Recyclerview 出现问题的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Android 中进行后台工作时使用 AsyncTask 显示 ProgressDialog? [复制]

Android - 传递按钮实例时避免 AsyncTask 中的内存泄漏

在 IntentService 和 AsyncTask (Android) 之间使用共享代码时,领域“从不正确的线程访问”错误

android asynctask怎么用

Android中的异步任务不使用AsyncTask

Android AsyncTask 和登录