使用 GSON 和 Volley 在 Android 上显示 JSON 数据

Posted

技术标签:

【中文标题】使用 GSON 和 Volley 在 Android 上显示 JSON 数据【英文标题】:Display JSON data on Android using GSON and Volley 【发布时间】:2017-06-30 08:36:39 【问题描述】:

您好,我是 android 编程新手,正在努力学习它。我遵循this 教程,它工作正常,但是我不知道如何在列表视图中显示记录。

PostActivity.java 文件来自下面的教程,

package com.kylewbanks.gsonvolleytutorial;

    import android.app.Activity;
    import android.os.Bundle;
    import android.util.Log;
    import android.widget.ArrayAdapter;

    import com.android.volley.Request;
    import com.android.volley.RequestQueue;
    import com.android.volley.Response;
    import com.android.volley.VolleyError;
    import com.android.volley.toolbox.StringRequest;
    import com.android.volley.toolbox.Volley;
    import com.google.gson.Gson;
    import com.google.gson.GsonBuilder;

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;

    import static android.R.id.list;

    public class PostActivity extends Activity 

        private static final String ENDPOINT = "https://kylewbanks.com/rest/posts.json";

        private RequestQueue requestQueue;
        private Gson gson;

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

            requestQueue = Volley.newRequestQueue(getApplicationContext());
            GsonBuilder gsonBuilder = new GsonBuilder();
            gsonBuilder.setDateFormat("M/d/yy hh:mm a");
            gson = gsonBuilder.create();

            fetchPosts();
        

        private void fetchPosts() 
            StringRequest request = new StringRequest(Request.Method.GET, ENDPOINT, onPostsLoaded, onPostsError);

            requestQueue.add(request);
        

        private final Response.Listener<String> onPostsLoaded = new Response.Listener<String>() 
            @Override
            public void onResponse(String response) 
                //Log.i(PostActivity.class.getSimpleName(), response);

                List<Post> posts = Arrays.asList(gson.fromJson(response, Post[].class));
                //Log.i(PostActivity.class.getSimpleName(), posts.size() + " posts loaded.");

                List listview = (List) findViewById(R.id.postListView);

                for (Post post : posts) 
                    //Log.i(PostActivity.class.getSimpleName(), post.ID + ": " + post.title);
                
                ArrayAdapter adapter = new ArrayAdapter(this,R.layout.single_post_item, posts);
                listview.setAdapter(adapter);

            
        ;

        private final Response.ErrorListener onPostsError = new Response.ErrorListener() 
            @Override
            public void onErrorResponse(VolleyError error) 
                Log.e(PostActivity.class.getSimpleName(), error.toString());
            
        ;
    

Post.java

import java.util.Date;
import com.google.gson.annotations.SerializedName;

public class Post 

    @SerializedName("id")
    long ID;

    @SerializedName("date")
    Date dateCreated;

    String title;
    String author;
    String url;
    String body;


activity_post.xml

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_
    android:layout_
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".PostActivity">

    <ListView
        android:layout_
        android:layout_
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:id="@+id/postListView"
        android:layout_alignParentBottom="true" />
</RelativeLayout>

single_post_item.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_
    android:layout_>

    <TextView
        android:text="TextView"
        android:layout_
        android:layout_
        android:id="@+id/textView" />
</LinearLayout>

更新错误 1:

:app:processDebugManifest
:app:processDebugResources
AGPBI: "kind":"error","text":"Error parsing XML: XML or text declaration not at start of entity","sources":["file":"C:\\Users\\xxx\\Downloads\\GSONVolleyTutorial-master\\GSONVolleyTutorial-master\\app\\src\\main\\res\\layout\\activity_post.xml","position":"startLine":0],"original":"","tool":"AAPT"
AGPBI: "kind":"error","text":"Error parsing XML: XML or text declaration not at start of entity","sources":["file":"C:\\Users\\xxx\\Downloads\\GSONVolleyTutorial-master\\GSONVolleyTutorial-master\\app\\src\\main\\res\\layout\\single_post_item.xml","position":"startLine":0],"original":"","tool":"AAPT"
C:\Users\xxx\Downloads\GSONVolleyTutorial-master\GSONVolleyTutorial-master\app\build\intermediates\res\merged\debug\layout\activity_post.xml:1: error: Error parsing XML: XML or text declaration not at start of entity

C:\Users\xxx\Downloads\GSONVolleyTutorial-master\GSONVolleyTutorial-master\app\build\intermediates\res\merged\debug\layout\single_post_item.xml:1: error: Error parsing XML: XML or text declaration not at start of entity

 FAILED

FAILURE: Build failed with an exception.

更新错误 2:

C:\Users\xxx\Downloads\GSONVolleyTutorial-master\GSONVolleyTutorial-master\app\src\main\java\com\kylewbanks\gsonvolleytutorial\PostActivity.java:70: error: no suitable constructor found for ArrayAdapter(<anonymous Listener<String>>,int,int,List<String>)
                ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,R.layout.single_post_item,R.id.textView, posts_strs);
                                               ^
    constructor ArrayAdapter.ArrayAdapter(Context,int,int,String[]) is not applicable
      (argument mismatch; <anonymous Listener<String>> cannot be converted to Context)
    constructor ArrayAdapter.ArrayAdapter(Context,int,int,List<String>) is not applicable
      (argument mismatch; <anonymous Listener<String>> cannot be converted to Context)
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
1 error

:app:compileDebugJavaWithJavac FAILED

FAILURE: Build failed with an exception.

【问题讨论】:

为什么是 Post[].class 而不是 Post.class? 可以添加single_post_item.xml的源码吗? 我添加了所有文件@GaëtanMaisse 我对 android 编程非常陌生,所以这就是我在教程中得到的 link@Nirel 【参考方案1】:

由于您的列表布局中只有一个TextView,因此您打算显示单个项目

1.) 创建一个String 数组列表并向其中添加元素

2.) 在创建适配器时提及@+id/textView" 作为第三个参数

ArrayAdapter(Context context, int resource, int textViewResourceId, List&lt;T&gt; objects)

public class PostActivity extends Activity 

    private static final String ENDPOINT = "https://kylewbanks.com/rest/posts.json";

    private RequestQueue requestQueue;
    private Gson gson;
    private List<String> posts_strs ;

    // keep it here for later use in other methods
    private List<Post> posts ;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        // code

        // initialize list
        posts_strs = new ArrayList<String>();

        // code
    


    private final Response.Listener<String> onPostsLoaded = new Response.Listener<String>() 
        @Override
        public void onResponse(String response) 
            //Log.i(PostActivity.class.getSimpleName(), response);

            posts = Arrays.asList(gson.fromJson(response, Post[].class));
            //Log.i(PostActivity.class.getSimpleName(), posts.size() + " posts loaded.");

            List listview = (List) findViewById(R.id.postListView);

            for (Post post : posts) 
                 // add items to list
                 posts_strs.add( post.ID + ": " + post.title);
                //Log.i(PostActivity.class.getSimpleName(), post.ID + ": " + post.title);
            
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(PostActivity.this,R.layout.single_post_item
                     ,R.id.textView, posts_strs);
            //   use the textview id posts_strs while creating adapter
            listview.setAdapter(adapter);

        
    ;
        // code


问题:

1.) 在XML 布局activity_postsingle_post_item 的顶部添加&lt;?xml version="1.0" encoding="utf-8"?&gt;

2.) 使用PostActivity.this 而不是this,因为this 将引用匿名Response.Listener&lt;String&gt; 类而不是PostActivity

【讨论】:

尝试更新后的代码,如果有错误,请提供详细信息 你必须在适配器中使用posts_strs 我及时在我的代码中更新了这个,只需尝试当前代码,肯定可以工作 我尝试了更新的代码,但错误如下:C:\Users\xxx\Downloads\GSONVolleyTutorial-master\GSONVolleyTutorial-master\app\src\main\res\layout\activity_post.xmlC:\Users\xxx\Downloads\GSONVolleyTutorial-master\GSONVolleyTutorial-master\app\src\main\res\layout\single_post_item.xml @Pavneet Singh 在你的帖子最后发布完整的错误,这些行只是路径,有有用的错误细节 是的,感谢您提供当前代码,它运行良好,我需要做一些如何使用 POST 方法并将操作和 id 参数发送到接受 post 请求的服务器。例如,我需要发送 operation=show,id=1 来获取 id 为 1 的列表 @Pavneet Singh【参考方案2】:
C:\Users\xxx\Downloads\GSONVolleyTutorial-master\GSONVolleyTutorial-master\app\src\main\java\com\kylewbanks\gsonvolleytutorial\PostActivity.java:70: error: no suitable constructor found for ArrayAdapter(<anonymous Listener<String>>,int,int,List<String>)
                ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,R.layout.single_post_item,R.id.textView, posts_strs);
                                               ^
    constructor ArrayAdapter.ArrayAdapter(Context,int,int,String[]) is not applicable
      (argument mismatch; <anonymous Listener<String>> cannot be converted to Context)
    constructor ArrayAdapter.ArrayAdapter(Context,int,int,List<String>) is not applicable
      (argument mismatch; <anonymous Listener<String>> cannot be converted to Context)

由于创建ArrayAdapter 的代码位于匿名内部类中,因此this 指的是该匿名类的实例。要访问包含匿名类的PostActivity 实例的this 指针,请改用PostActivity.this

【讨论】:

以上是关于使用 GSON 和 Volley 在 Android 上显示 JSON 数据的主要内容,如果未能解决你的问题,请参考以下文章

如何在 android 中使用 Gson 或 VOLley 从 json 中删除空值

Android实战--英文词典(API+GSON+Volley)

Android实战--英文词典(API+GSON+Volley)

如何在Bazel中为Android项目添加Maven依赖项(例如Volley,Gson)?

Kotlin编程开发Android运用程序(Volley+Gson依赖库)

启用 ProGuard 规则时 Gson 解析不起作用