【问题标题】:Creating a custom ArrayAdapter and filling a ListView with a requested Json using Volley使用 Volley 创建自定义 ArrayAdapter 并使用请求的 Json 填充 ListView
【发布时间】:2016-05-24 19:59:16
【问题描述】:

我已经坚持这个练习太久了。

我已经获得了部分代码,而我必须编写其余部分。

首先,我有一个 VolleyManager 类,它可以帮助使用一些 Volley 工具(例如添加到请求队列)。然后是另一个帮助解析请求的 Json 的 Gson 类。

这是 UserListFragment 的代码,其中有两个按钮。一个用于填充列表,一个用于清除列表,以及这两个按钮下方的列表本身。

public class UserListFragment extends Fragment {

private static final String USERS_URL = "https://raw.githubusercontent.com/bengui/volleytest/master/json/users.json";
private static final String TAG = UserListFragment.class.getSimpleName();

private View view;
private ListAdapter listAdapter;
private Button requestButton;
private Button cleanButton;
private ListView listView;

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    view = inflater.inflate(R.layout.fragment_user_list, null);

    // UI Elements
    requestButton = (Button) view.findViewById(R.id.request_btn);
    listView = (ListView) view.findViewById(R.id.listview_users);
    requestButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            listAdapter = new ListAdapter(view.getContext());
            listView.setAdapter(listAdapter);
        }
    });

    cleanButton = (Button) view.findViewById(R.id.clean_btn);
    cleanButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            listView.setAdapter(null);
        }
    });
    return view;
}

这是我为填充列表中的元素而制作的个性化适配器。

   public class ListAdapter extends ArrayAdapter {

        VolleyManager volleyManager;
        List<User> list;

        public ListAdapter(Context context){
            super(context,0);
            volleyManager = VolleyManager.getInstance(getActivity());

            requestButton.setEnabled(false);

            JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(
                    USERS_URL,
                    new Response.Listener<JSONArray>() {
                        @Override
                        public void onResponse(JSONArray response) {
                            list = parseUserList(response.toString());
                            requestButton.setEnabled(true);
                            notifyDataSetChanged();
                        }
                    },
                    new Response.ErrorListener() {
                        @Override
                        public void onErrorResponse(VolleyError error){
                            Log.d(TAG, "JSON response error : " + error.getMessage());
                            requestButton.setEnabled(true);
                        }
                    }
            );
            volleyManager.addToRequestQueue(jsonArrayRequest);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());

            View listItemView = convertView;

            if (null == convertView) {
                listItemView = layoutInflater.inflate(
                        R.layout.fragment_list_item,
                        parent,
                        false);
            }

            // Pick an element of the list and fill the UI textViews.
            User user = list.get(position);

            TextView nombre = (TextView) listItemView.findViewById(R.id.user_name);
            TextView apellido = (TextView) listItemView.findViewById(R.id.user_last_name);
            TextView edad = (TextView) listItemView.findViewById(R.id.user_age);

            // Update views
            nombre.setText(user.getName());
            apellido.setText(user.getLastName());
            edad.setText(user.getAge());

            return listItemView;
        }
    }

    /**
     * Parses a users json array into a users list.
     *
     * @param jsonArray
     *
     * @return Users list
     */
    private List<User> parseUserList(String jsonArray) {
        Gson gson = new Gson();

        // Declares the list type
        Type listType = new TypeToken<List<User>>() {}.getType();

        List<User> userList = gson.fromJson(jsonArray, listType);

        return userList;
    }
}

我不确定为什么这不起作用。也许我不完全了解适配器的工作原理,并且我在按钮单击侦听器上进行了错误调用?

一个多星期以来,我一直在努力解决这个问题。 取得了一些进展!但仍然无法成功。

欢迎任何意见。

编辑:忘记 .xmls

这是片段的布局。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_user_list"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">

<Button
    android:id="@+id/request_btn"
    android:text="@string/request_btn"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

<Button
    android:id="@+id/clean_btn"
    android:text="@string/clean_btn"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

<ListView
    android:id="@+id/listview_users"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

</LinearLayout>

这是列表视图项的布局。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
    android:id="@+id/user_name"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

<TextView
    android:id="@+id/user_last_name"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

<TextView
    android:id="@+id/user_age"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

</LinearLayout>

【问题讨论】:

  • 到底是什么问题?不显示列表吗?
  • 是的,显示屏上什么也不显示。但数据已被检索。
  • 你检查 getView 在你的列表变量被填充后被调用了吗?
  • 另外,在您的列表视图项目布局中,您的 LinearLayout 方向是否应该是水平的,因为子视图具有 width="match_parent"?
  • 我认为 getView 没有被调用,但我不确定应该在哪里调用..!会继续研究。关于LinearLayout,你是对的,它们的宽度是错误的。也会解决这个问题,所以一切都会出现。谢谢大佬!

标签: java android json gson android-volley


【解决方案1】:

尝试使用recycler_View... Recycler_View 可以管理很多你不需要担心的事情......

【讨论】:

  • RecyclerView 是我需要研究的一个主题......我认为它只能通过创建更少的列表项来提高性能?
  • 在你的 onCreate() 方法中试试这个...ListAdapter customAdapter = new ListAdapter(this, R.layout.list_item, tempList);
  • 我认为该行适用于每个列表项只有一个文本视图的情况。在这种情况下,列表中的每个项目都有 3 个 textView,这就是我必须制作自定义适配器的原因。
【解决方案2】:

为了将 Json 解析为 listView,请执行以下步骤: 1- 创建一个类将保存来自 json 对象的数据,如下所示:

public class Person {

    String name;
    String last_name;
    String age;

    public Person() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getLast_name() {
        return last_name;
    }

    public void setLast_name(String last_name) {
        this.last_name = last_name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
} 

2- 创建一个类并将其命名为 Adapter 以将其设置为列表视图,如下所示:

import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.List;
public class Adapter extends BaseAdapter{

    private LayoutInflater inflater;
    private Activity activity;
    private List<Person> persons;
   private TextView userName ;
    private TextView  lastName;
    private TextView age ;

    public Adapter(Activity activity, List<Person> items){
        this.activity=activity;
        this.persons=items;
    }
    @Override
    public int getCount() {
        return persons.size();
    }

    @Override
    public Object getItem(int position) {
        return persons.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {



            if(inflater==null){
                inflater=(LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            }
            if(convertView ==null){
                convertView=inflater.inflate(R.layout.custom_layout,null);

            }

        userName=(TextView)convertView.findViewById(R.id.user_name);
        lastName=(TextView)convertView.findViewById(R.id.last_name);
        age=(TextView)convertView.findViewById(R.id.age);

        Person person=persons.get(position);

        userName.setText("Name:"+person.getName());
        lastName.setText("LastName:"+person.getLast_name());
        age.setText("Age"+person.getAge());

        return convertView;
    }
}

3- 在您要填充列表视图元素的片段内部(我在此片段中使用了相同的 json 链接,它成功运行):

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
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.JsonArrayRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;

public class PersonFragment extends Fragment {

    private static final String JSON_URL = "https://raw.githubusercontent.com/bengui/volleytest/master/json/users.json";
    public static List<Person> personList = new ArrayList<>();
    private ListView listView;
    public static Adapter adapter;

    public PersonFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
       View view=inflater.inflate(R.layout.your_fragment_layout, container, false);
        listView = (ListView)view.findViewById(R.id.persons_listView);
        adapter=new Adapter(getActivity(),personList);
        listView.setAdapter(adapter);
        setListViewData();

        return  view;
    }

    private void setListViewData() {


        RequestQueue requestQueue = Volley.newRequestQueue(getContext());
        JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Request.Method.GET, JSON_URL, new Response.Listener<JSONArray>() {
            public void onResponse(JSONArray jsonArray) {
                if (jsonArray.length() > 0) {

                    for (int i = 0; i < jsonArray.length(); i++) {
                        try {

                            JSONObject obj = jsonArray.getJSONObject(i);
                            Person person =new Person();
                            person.setName(obj.getString("name"));
                            person.setLast_name(obj.getString("last_name"));
                            person.setAge(obj.getString("age"));

                            personList.add(person);

                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                        adapter.notifyDataSetChanged();
                    }
                }

            }
            // setArrayListLength(titles);
            //  Toast.makeText(getApplicationContext(),""+titles.size(),Toast.LENGTH_SHORT
            //).show();

        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                Log.e("Error", "Unable to parse json array2");
            }
        });
        // add json array request to the request queue
        requestQueue.add(jsonArrayRequest);


    }
} 

4- 像这样在 Layout 文件夹 custom_layout.xml 中创建:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout

xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
        <TextView
            android:id="@+id/user_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="userName"
            android:textSize="20dp"/>

        <TextView
            android:id="@+id/last_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="userName"
            android:textSize="20dp"
           android:paddingTop="10dp"

            />

    <TextView

        android:id="@+id/age"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="userName"
        android:paddingTop="10dp"
        />

</LinearLayout>

5- 在 Layout 文件夹中创建另一个 xml 资源并将其命名为 your_fragment_layout.xml,如下所示:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
   >


    <ListView
        android:id="@+id/persons_listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:dividerHeight="5dp"
        ></ListView>


</RelativeLayout>

最后不要忘记这个依赖添加到你的项目 gradle 中

 compile 'com.mcxiaoke.volley:library:1.0.17'

另外不要忘记将 Internet 权限添加到您的清单文件中,如下所示:

<uses-permission android:name="android.permission.INTERNET" />

我测试了这个片段,它运行成功。希望这对您有所帮助。

【讨论】:

  • 嘿,感谢所有这些。当我复制粘贴它的作品。我只需要从 json 请求中删除一个参数(不需要 Request.Method.GET 参数,因为它是从它自己的构造函数中自动调用的,即使我认为你给我的代码行无论如何都应该工作)。我仍然会尝试通过按钮使其工作,现在我有一些工作代码!再次感谢伙计!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-25
相关资源
最近更新 更多