有没有更好的方法在使用 volley 获取数据的同时在片段中填充 listView?
Is there a better way to populate a listView in a fragment while getting the data with volley?
我正在做一个练习,我必须通过 Volley 库从服务器获取一个 JSONArray 对象。然后用该数据填充一个 listView。我已经做到了,但我认为必须有更好的方法。我想出的唯一方法是在我发送给 volley 的 JSONArrayRequest 的 onResponse 方法中设置适配器。
是否可以在fragment的onCreateView方法中设置适配器?
这是我的代码:
public class UserListFragment extends Fragment {
private static final String USERS_URL = "https://raw.githubusercontent.com/users.json";
public static final String TAG = UserListFragment.class.getSimpleName();
private ListView listView;
private VolleyManager volleyManager;
private List<User> users;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_user_list, null);
listView = (ListView) view.findViewById(R.id.list_view);
Button obtain_data_btn = (Button) view.findViewById(R.id.user_list_obtain_btn);
obtain_data_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getUsersListData();
}
});
return view;
}
private void getUsersListData() {
JsonArrayRequest jsonArrayRqst = new JsonArrayRequest(
USERS_URL,
new Response.Listener<JSONArray>(){
@Override
public void onResponse(JSONArray response) {
users = parseUserList(response.toString());
listView.setAdapter(new UsersAdapter(getActivity(), R.layout.list_item, users));
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, error.getMessage());
}
}
);
volleyManager = VolleyManager.getInstance(getActivity());
volleyManager.addToRequestQueue(jsonArrayRqst);
}
/**
* 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;
}
private class UsersAdapter extends ArrayAdapter<User> {
public UsersAdapter(Context context, int itemResourceId) {
super(context, itemResourceId);
}
public UsersAdapter(Context context, int resource, List<User> users) {
super(context, resource, users);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View listItemView = convertView;
if (listItemView == null) {
LayoutInflater layoutInflater;
layoutInflater = LayoutInflater.from(getContext());
listItemView = layoutInflater.inflate(R.layout.list_item, null);
}
User user = getItem(position);
TextView userNameTV = (TextView) listItemView.findViewById(R.id.userName_userList);
TextView userLastNameTV = (TextView) listItemView.findViewById(R.id.userLastName_userList);
TextView userAgeTV = (TextView) listItemView.findViewById(R.id.userAge_userList);
userNameTV.setText(user.getName());
userLastNameTV.setText(user.getLastName());
userAgeTV.setText(Integer.toString(user.getAge()));
return listItemView;
}
}
}
是的,我在当前项目片段的 onCreateView 中将我的适配器设置为 ExpandableListView。这样做应该没有问题。
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View parentThis = (LinearLayout)inflater.inflate(R.layout.tab_exlv, container, false);
exlvTabHistory = (ExpandableListView)parentThis.findViewById(R.id.exlvTabHistory);
exlvTabHistory.setAdapter(setupEXLVAdapter());
}
是的,有更好的方法。创建对您的 Adapter 的引用作为 Fragment 的成员变量,这允许您在数据进来后调用 notifyDataSetChanged()
。
有一点需要注意,您不能更改数据源的引用,即 users
列表。所以,当数据进来的时候,使用addAll()
添加数据,不用重新分配数据源引用。
你的代码应该是这样的:
public class UserListFragment extends Fragment {
private static final String USERS_URL = "https://raw.githubusercontent.com/users.json";
public static final String TAG = UserListFragment.class.getSimpleName();
private ListView listView;
private VolleyManager volleyManager;
private List<User> users;
UsersAdapter adapter; //added
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_user_list, null);
listView = (ListView) view.findViewById(R.id.list_view);
//added:
adapter = new UsersAdapter(getActivity(), R.layout.list_item, users);
listView.setAdapter(adapter);
Button obtain_data_btn = (Button) view.findViewById(R.id.user_list_obtain_btn);
obtain_data_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getUsersListData();
}
});
return view;
}
private void getUsersListData() {
JsonArrayRequest jsonArrayRqst = new JsonArrayRequest(
USERS_URL,
new Response.Listener<JSONArray>(){
@Override
public void onResponse(JSONArray response) {
//modified:
users.addAll(parseUserList(response.toString()));
adapter.notifyDataSetChanged();
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, error.getMessage());
}
}
);
volleyManager = VolleyManager.getInstance(getActivity());
volleyManager.addToRequestQueue(jsonArrayRqst);
}
//.........
我正在做一个练习,我必须通过 Volley 库从服务器获取一个 JSONArray 对象。然后用该数据填充一个 listView。我已经做到了,但我认为必须有更好的方法。我想出的唯一方法是在我发送给 volley 的 JSONArrayRequest 的 onResponse 方法中设置适配器。
是否可以在fragment的onCreateView方法中设置适配器?
这是我的代码:
public class UserListFragment extends Fragment {
private static final String USERS_URL = "https://raw.githubusercontent.com/users.json";
public static final String TAG = UserListFragment.class.getSimpleName();
private ListView listView;
private VolleyManager volleyManager;
private List<User> users;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_user_list, null);
listView = (ListView) view.findViewById(R.id.list_view);
Button obtain_data_btn = (Button) view.findViewById(R.id.user_list_obtain_btn);
obtain_data_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getUsersListData();
}
});
return view;
}
private void getUsersListData() {
JsonArrayRequest jsonArrayRqst = new JsonArrayRequest(
USERS_URL,
new Response.Listener<JSONArray>(){
@Override
public void onResponse(JSONArray response) {
users = parseUserList(response.toString());
listView.setAdapter(new UsersAdapter(getActivity(), R.layout.list_item, users));
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, error.getMessage());
}
}
);
volleyManager = VolleyManager.getInstance(getActivity());
volleyManager.addToRequestQueue(jsonArrayRqst);
}
/**
* 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;
}
private class UsersAdapter extends ArrayAdapter<User> {
public UsersAdapter(Context context, int itemResourceId) {
super(context, itemResourceId);
}
public UsersAdapter(Context context, int resource, List<User> users) {
super(context, resource, users);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View listItemView = convertView;
if (listItemView == null) {
LayoutInflater layoutInflater;
layoutInflater = LayoutInflater.from(getContext());
listItemView = layoutInflater.inflate(R.layout.list_item, null);
}
User user = getItem(position);
TextView userNameTV = (TextView) listItemView.findViewById(R.id.userName_userList);
TextView userLastNameTV = (TextView) listItemView.findViewById(R.id.userLastName_userList);
TextView userAgeTV = (TextView) listItemView.findViewById(R.id.userAge_userList);
userNameTV.setText(user.getName());
userLastNameTV.setText(user.getLastName());
userAgeTV.setText(Integer.toString(user.getAge()));
return listItemView;
}
}
}
是的,我在当前项目片段的 onCreateView 中将我的适配器设置为 ExpandableListView。这样做应该没有问题。
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View parentThis = (LinearLayout)inflater.inflate(R.layout.tab_exlv, container, false);
exlvTabHistory = (ExpandableListView)parentThis.findViewById(R.id.exlvTabHistory);
exlvTabHistory.setAdapter(setupEXLVAdapter());
}
是的,有更好的方法。创建对您的 Adapter 的引用作为 Fragment 的成员变量,这允许您在数据进来后调用 notifyDataSetChanged()
。
有一点需要注意,您不能更改数据源的引用,即 users
列表。所以,当数据进来的时候,使用addAll()
添加数据,不用重新分配数据源引用。
你的代码应该是这样的:
public class UserListFragment extends Fragment {
private static final String USERS_URL = "https://raw.githubusercontent.com/users.json";
public static final String TAG = UserListFragment.class.getSimpleName();
private ListView listView;
private VolleyManager volleyManager;
private List<User> users;
UsersAdapter adapter; //added
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_user_list, null);
listView = (ListView) view.findViewById(R.id.list_view);
//added:
adapter = new UsersAdapter(getActivity(), R.layout.list_item, users);
listView.setAdapter(adapter);
Button obtain_data_btn = (Button) view.findViewById(R.id.user_list_obtain_btn);
obtain_data_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getUsersListData();
}
});
return view;
}
private void getUsersListData() {
JsonArrayRequest jsonArrayRqst = new JsonArrayRequest(
USERS_URL,
new Response.Listener<JSONArray>(){
@Override
public void onResponse(JSONArray response) {
//modified:
users.addAll(parseUserList(response.toString()));
adapter.notifyDataSetChanged();
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, error.getMessage());
}
}
);
volleyManager = VolleyManager.getInstance(getActivity());
volleyManager.addToRequestQueue(jsonArrayRqst);
}
//.........