将解析的 JSONArray 加载到 recyclerView

Posted

技术标签:

【中文标题】将解析的 JSONArray 加载到 recyclerView【英文标题】:Loading parsed JSONArray into a recyclerView 【发布时间】:2020-09-10 14:49:48 【问题描述】:

我正在尝试将 API 调用的结果加载到 recyclerView 中。我创建了一个数据模型来保存要用于填充 recyclerView 适配器的结果数组(字符串)。但是一旦解析了 JSON 文件,应用程序会在调用数据模型的“setValues”时崩溃,但结果会准确地显示在 logcat 上。 我的代码如下:

MainActivity

package com.limitless.googlebooks;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.loader.app.LoaderManager;
import androidx.loader.content.Loader;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.net.NetworkInterface;
import java.util.ArrayList;

import static android.text.TextUtils.isEmpty;

public class MainActivity extends AppCompatActivity
        implements LoaderManager.LoaderCallbacks<String> 
    private EditText bookImput;
    private RecyclerView recyclerView;
    private ProgressBar progressBar;
    private static Books books;
    ArrayList<Books> booksArray;

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

        bookImput = findViewById(R.id.bookInput);
        progressBar = findViewById(R.id.progressBar);
        recyclerView = findViewById(R.id.bookRecyclerView);
        booksArray =  new ArrayList<>();
        BooksAdapter adapter = new BooksAdapter(booksArray);
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        if(LoaderManager.getInstance(this).getLoader(0) != null)
            LoaderManager.getInstance(this).initLoader(0,null, this);
        
    

    public void searchBooks(View view) 
        String queryText = bookImput.getText().toString();
        InputMethodManager methodManager = (InputMethodManager)
                getSystemService(Context.INPUT_METHOD_SERVICE);
        if(methodManager != null)
            methodManager.hideSoftInputFromWindow(view.getWindowToken(),
                    methodManager.HIDE_NOT_ALWAYS);
        
        ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = null;
        if(connectivityManager != null)
            networkInfo = connectivityManager.getActiveNetworkInfo();
        
        if(networkInfo != null && !isEmpty(queryText) && networkInfo.isConnected())
            Bundle queryBundle = new Bundle();
            queryBundle.putString("queryString", queryText);
            LoaderManager.getInstance(this).restartLoader(0, queryBundle, this);
            progressBar.setVisibility(View.VISIBLE);
        else 
            if(isEmpty(queryText))
                Toast.makeText(this, R.string.emptyquery, Toast.LENGTH_SHORT).show();
            else
                Toast.makeText(this, R.string.no_internet, Toast.LENGTH_SHORT).show();
            
        
    

    @NonNull
    @Override
    public Loader<String> onCreateLoader(int id, @Nullable Bundle args) 
        String queryString = "";
        if(args != null)
            queryString = args.getString("queryString");
        
        return new BookLoader(this, queryString);
    

    @Override
    public void onLoadFinished(@NonNull Loader<String> loader, String data) 
        try
            JSONObject jsonObject = new JSONObject(data);
            JSONArray itemsArray = jsonObject.getJSONArray("items");

            int i = 0;
            String title = null;
            String authors = null;
            String publisher = null;
            String date = null;

            while(i < itemsArray.length() && title == null && authors == null && date == null)
                JSONObject book = itemsArray.getJSONObject(i);
                JSONObject volumeInfo = book.getJSONObject("volumeInfo");
                try
                    title = volumeInfo.getString("title");
                    authors = volumeInfo.getString("authors");
                    publisher = volumeInfo.getString("publisher");
                    date = volumeInfo.getString("publishedDate");
                 catch (JSONException e) 
                    e.printStackTrace();
                
                i++;
            
            if(title != null && authors != null && date != null)
                books.setBookName(title);
                books.setAuthorsName(authors);
                books.setPublisher(publisher);
                books.setPublishedDate(date);
                booksArray.add(books);
            else 
                books.setBookName(String.valueOf(R.string.no_results));
                books.setAuthorsName("");
                books.setPublisher("");
                books.setPublishedDate("");;
            
        catch (JSONException e)
            books.setBookName(String.valueOf(R.string.error));
            books.setAuthorsName("");
            books.setPublisher("");
            books.setPublishedDate("");
            e.printStackTrace();

        
    

    @Override
    public void onLoaderReset(@NonNull Loader<String> loader) 

    

数据模型

package com.limitless.googlebooks;

public class Books 
    private String bookName;
    private String authorsName;
    private String publisher;
    private String publishedDate;

    public Books(String bookName, String authorsName, String publisher, String publishedDate) 
        this.bookName = bookName;
        this.authorsName = authorsName;
        this.publisher = publisher;
        this.publishedDate = publishedDate;
    
    public Books()


    public String getBookName() 
        return bookName;
    

    public void setBookName(String bookName) 
        this.bookName = bookName;
    

    public String getAuthorsName() 
        return authorsName;
    

    public void setAuthorsName(String authorsName) 
        this.authorsName = authorsName;
    

    public String getPublisher() 
        return publisher;
    

    public void setPublisher(String publisher) 
        this.publisher = publisher;
    

    public String getPublishedDate() 
        return publishedDate;
    

    public void setPublishedDate(String publishedDate) 
        this.publishedDate = publishedDate;
    

适配器类

package com.limitless.googlebooks;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;

public class BooksAdapter extends RecyclerView.Adapter<BooksAdapter.BooksHolder>
    ArrayList<Books> booksArrayList;
    public BooksAdapter(ArrayList<Books> booksArray)
        this.booksArrayList = booksArray;
        

    @NonNull
    @Override
    public BooksHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) 
        Context context = parent.getContext();
        View itemView = LayoutInflater.from(context).inflate(R.layout.booklist, parent, false);
        return new BooksHolder(itemView);
    

    @Override
    public void onBindViewHolder(@NonNull BooksHolder holder, int position) 
        Books books = booksArrayList.get(position);
        holder.bind(books);
    

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

    public class BooksHolder extends RecyclerView.ViewHolder 
        private TextView bookName;
        private TextView authorsName;
        private TextView publisher;
        private TextView publishedDate;

        public BooksHolder(@NonNull View itemView) 
            super(itemView);

            bookName = itemView.findViewById(R.id.bookTitle);
            authorsName = itemView.findViewById(R.id.authorsName);
            publisher = itemView.findViewById(R.id.publisher);
            publishedDate = itemView.findViewById(R.id.publishedDate);
        

        public void bind(Books books)
            bookName.setText(books.getBookName());
            authorsName.setText(books.getAuthorsName());
            publisher.setText(books.getPublisher());
            publishedDate.setText(books.getPublishedDate());
        
    


【问题讨论】:

你能把你得到的错误贴在日志上吗? 你能从 logcat 打印错误吗?这将有助于我们正确理解根本原因。 【参考方案1】:

在你的MainActivity:

这些

public class MainActivity extends AppCompatActivity
        implements LoaderManager.LoaderCallbacks<String> 
....
    private static Books books;
    ArrayList<Books> booksArray;

变成:

public class MainActivity extends AppCompatActivity
        implements LoaderManager.LoaderCallbacks<String> 
....  
    private Books books;
    private ArrayList<Books> booksArray;
    private BooksAdapter adapter;

onCreate():

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

        ........
        adapter = new BooksAdapter(booksArray);
        ........
        ........



现在在onLoadFinished():

这个:

        if(title != null && authors != null && date != null)
            books.setBookName(title);
            books.setAuthorsName(authors);
            books.setPublisher(publisher);
            books.setPublishedDate(date);
            booksArray.add(books);
        else 
            books.setBookName(String.valueOf(R.string.no_results));
            books.setAuthorsName("");
            books.setPublisher("");
            books.setPublishedDate("");;
        
    catch (JSONException e)
        books.setBookName(String.valueOf(R.string.error));
        books.setAuthorsName("");
        books.setPublisher("");
        books.setPublishedDate("");
        e.printStackTrace();

    

变成:

        if(title != null && authors != null && date != null)

            books = new Books(title,authors,publisher,date);
            booksArray.add(books);
            adapter.notifyDataSetChanged();


        else 

            books = new Books(String.valueOf(R.string.no_results),"","","");

            //if you want to add them to array add them, if not then don't
            booksArray.add(books);
            adapter.notifyDataSetChanged();
        
    catch (JSONException e)

            books = new Books(String.valueOf(R.string.error),"","","");

            //if you want to add them to array add them, if not then don't
            booksArray.add(books);
            adapter.notifyDataSetChanged();
            e.printStackTrace();

    

【讨论】:

谢谢。我注意到我没有在 onCreate 中实例化 Books 对象。但是您的回答帮助我解决了另一个难题。我很感激 如果这有助于接受答案,以便其他有同样问题的人知道这是一个解决方案。祝你好运。

以上是关于将解析的 JSONArray 加载到 recyclerView的主要内容,如果未能解决你的问题,请参考以下文章

使用 SwiftyJSON 将 JSONArray 解析为字符串数组

jsonarray 哪个性能好

Kotlin:遍历 JSONArray

JSONJSONObject 与 JSONArray 详细介绍及其应用方式

JSONArray jsonary = (JSONArray) JSONObject.parse(s); 是啥意思

无法使用改造解析对象内部 jsonarray 的 jsonarray?