问题
This is a follow-up to my previous question: Parse RecyclerView Image Query
I am now having a paradoxical nullpointer exception. I am attempting to extract a list from an inner method, in the way outlined below.
public List<ParseObject> objectList;
public List<String> getData(String filter){
ParseQuery<ParseObject> query = ParseQuery.getQuery("Images");
query.whereEqualTo("category", filter);
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> downloads, com.parse.ParseException e) {
if (e == null) {
objectList=downloads;
} else {
Log.d("score", "Error: " + e.getMessage());
}
}
});
int size = objectList.size();
for (int i = 0; i<size; i++){
ParseFile file = (ParseFile) objectList.get(i).get("Image");
urlList.add(file.getUrl());
}
return urlList;
}
How do I solve this? What ways exist which are better than what I am using?
EDIT:
Here is what it's doing. At present there are no exceptions, but the recyclerview is not displaying anything.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_events, container, false);
setList("sport", rootView);
return rootView;
}
public void set() {
}
public void setList(String filter, View view){
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.rv);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(linearLayoutManager);
MyAdapter myAdapter = new MyAdapter(getData(filter));
recyclerView.setAdapter(myAdapter);
}
EDIT 2: More updated code:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_events, container, false);
setList("sport", rootView);
return rootView;
}
public void set() {
}
public void setList(String filter, View view){
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.rv);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(linearLayoutManager);
MyAdapter myAdapter = new MyAdapter(getData(filter));
recyclerView.setAdapter(myAdapter);
}
private List<String> urlList = new ArrayList<>();
public List<ParseObject> objectList = new ArrayList<>();
public int size;
public List<String> getData(String filter){
ParseQuery<ParseObject> query = ParseQuery.getQuery("Images");
query.whereEqualTo("category", filter);
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> downloads, com.parse.ParseException e) {
if (e == null) {
Toast.makeText(getActivity(), "Downloads retrieved", Toast.LENGTH_SHORT).show();
objectList.addAll(downloads);
} else {
Log.d("score", "Error: " + e.getMessage());
}
size = objectList.size();
}
});
for (int i = 0; i<size; i++){
ParseFile file = (ParseFile) objectList.get(i).get("Image");
urlList.add(file.getUrl());
}
return urlList;
}
EDIT 3: Updated, and I have added my adapter code.
View rootView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.activity_events, container, false);
new GetUrlListTask(this).execute("sport");
return rootView;
}
public void set() {
}
private List<String> urlList = new ArrayList<>();
public List<ParseObject> objectList = new ArrayList<>();
public int size;
public List<String> getData(String filter){
ParseQuery<ParseObject> query = ParseQuery.getQuery("Images");
query.whereEqualTo("category", filter);
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> downloads, com.parse.ParseException e) {
if (e == null) {
Toast.makeText(getActivity(), "Downloads retrieved", Toast.LENGTH_SHORT).show();
objectList.addAll(downloads);
} else {
}
size = objectList.size();
}
});
for (int i = 0; i<size; i++){
ParseFile file = (ParseFile) objectList.get(i).get("Image");
urlList.add(file.getUrl());
}
return urlList;
}
private class GetUrlListTask extends AsyncTask<String,Void,List<String>>
{
private WeakReference<Fragment> weakRef;
public GetUrlListTask(Fragment frag){
weakRef = new WeakReference< Fragment >(frag);
}
@Override
protected List<String> doInBackground(String... filters) {
return getData(filters[0]);
}
@Override
protected void onPostExecute(List<String> urlList) {
Fragment frag = weakRef.get();
if (frag != null){
RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.rv);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(linearLayoutManager);
MyAdapter myAdapter = new MyAdapter(urlList);
recyclerView.setAdapter(myAdapter);
}
}
}
And My adapter:
List<String> urls;
ViewGroup parent;
public MyAdapter(List<String> urls){
this.urls=urls;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.image_entry, parent);
MyViewHolder myViewHolder = new MyViewHolder(view);
this.parent=parent;
return myViewHolder;
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Picasso.with(parent.getContext())
.load(urls.get(position))
.into(holder.photo);
Toast.makeText(parent.getContext(), urls.get(position), Toast.LENGTH_LONG).show();
}
@Override
public int getItemCount() {
return urls.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder{
ImageView photo;
public MyViewHolder(View itemView) {
super(itemView);
photo = (ImageView) itemView.findViewById(R.id.listImage);
}
}
回答1:
So I am assuming that what you want to do is once you get the urlList, you want to update some view. If that's the case then I think what you want to do it run that whole method in a background task rather than just the query like so:
First change your getData() method:
public List<String> getData(String filter){
ParseQuery<ParseObject> query = ParseQuery.getQuery("Images");
query.whereEqualTo("category", filter);
objectList = query.find(); //I think you have to surround this by a try catch or have the method throw an exception
int size = objectList.size();
for (int i = 0; i<size; i++){
ParseFile file = (ParseFile) objectList.get(i).get("Image");
urlList.add(file.getUrl());
}
return urlList;
}
Note that since you are doing a network call, the above method now HAS to run from a background thread.
Then you can use something like an AsyncTask to update a view:
private class GetUrlListTask extends AsyncTask<String,Void,List<String>>
{
private WeakReference<Fragment> weakRef;
public PhotoTagsFetchTask(Fragment frag){
weakRef = new WeakReference< Fragment >(frag);
}
@Override
protected Void doInBackground(String... filters) {
return getData(filters[0]);
}
@Override
protected void onPostExecute(List<String> urlList) {
Fragment frag = weakRef.get();
if (frag != null){
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.rv);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(linearLayoutManager);
MyAdapter myAdapter = new MyAdapter(urlList);
recyclerView.setAdapter(myAdapter);
}
}
}
Note that the use of weak reference above is to avoid context leaks (basically avoids unnecessary memory leaks).
You could also do this:
public void getData(String filter){
ParseQuery<ParseObject> query = ParseQuery.getQuery("Images");
query.whereEqualTo("category", filter);
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> downloads, com.parse.ParseException e) {
if (e == null) {
objectList=downloads;
int size = objectList.size();
for (int i = 0; i<size; i++){
ParseFile file = (ParseFile) objectList.get(i).get("Image");
urlList.add(file.getUrl());
}
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.rv);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(linearLayoutManager);
MyAdapter myAdapter = new MyAdapter(urlList);
recyclerView.setAdapter(myAdapter);
} else {
Log.d("score", "Error: " + e.getMessage());
}
}
});
}
回答2:
Change objectList=downloads
to objectList.addAll(downloads)
and add objectList = new ArrayList<>()
in the first line.
Also move the section starting fromobjectList.size()
inside the done
method of query callback
来源:https://stackoverflow.com/questions/31840590/parsequery-nullpointer-exception-paradox