NullPointerException on view.findViewById() with Parse Query



我使用带有解析查询适配器的自定义适配器填充了一个列表视图。我的问题是我似乎只能访问列表的第一项。在列表视图中,我有一个要调用函数的按钮。

    android:id="@+id/showGrunts"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:layout_below="@id/buttonthang"
    android:clickable="true"
    android:onClick="displayGruntList"

这是单击按钮时调用的函数:

public void displayGruntList(View view) {
    TextView objectID = (TextView) findViewById(R.id.tvPostIDCheese);
    String id = objectID.getText().toString();
    //String id = ((TextView)(view.findViewById(R.id.tvPostIDCheese))).getText().toString();
    Intent i = new Intent(GruntrMain.this, GruntList.class);
    Bundle idData = new Bundle();
    idData.putString("id", id);
    i.putExtras(idData);
    startActivity(i);
}

请注意注释行。我的问题是,如果我单击此按钮,它只会显示 ListView 第一项的相关项,即使我单击列表中其他项的按钮也是如此。我已经能够通过在获取 ID 后将其显示为 Toast 来确定这一点。无论我单击哪一个,它始终显示列表中顶部项目的 ID。如果我对它们重新排序,并且通过在每个列表项中显示 ID,我相信这在我的查询中不是问题,因为它们都以正确的 ID 显示。

我对传递给函数的视图的理解是,它来自正在选择的实际项。我见过其他使用 view.findViewById() 的代码,但是当我尝试这样做时,该行给了我一个 NullPointerException。我希望能够做的是从该特定项目的 TextView 中获取文本(表示 ID)。同样,使用我目前拥有的代码,它只会从第一项中抓取该文本。所以问题不在于我的解析查询,而在于我如何访问它。下面可以看到发生此问题的整个.java文件。

package com.snowflakes.gruntr;
import java.util.List;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import com.parse.FindCallback;
import com.parse.GetCallback;
import com.parse.ParseException;
import com.parse.ParseObject;
import com.parse.ParseQuery;
import com.parse.ParseQueryAdapter;
import com.parse.ParseRelation;
import com.parse.ParseUser;
public class GruntrMain extends Activity {
private static final int LOGIN_REQUEST = 0;
private ListView listView;
private ParseQueryAdapter<ParseObject> mainAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setContentView(R.layout.gruntr_main);
    ImageView addF = (ImageView) findViewById(R.id.ivAddFriend);
    final ImageView fReq = (ImageView) findViewById(R.id.ivFriendRequest);
    ImageView mPost = (ImageView) findViewById(R.id.ivMakePost);
    mainAdapter = new CustomAdapter(this);
    listView = (ListView) findViewById(R.id.lvPostList);
    listView.setAdapter(mainAdapter);
    mainAdapter.loadObjects();
    Thread refreshFeed = new Thread() {
        public void run() {
            while (true) {
                try {
                    sleep(20000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    mainAdapter.loadObjects();
                }
            }
        }// public void run()
    }; // new Thread()
    refreshFeed.start();
    // This thread is used for friend polling
    // In order to get it to run repeatedly, may need to make an infinite
    // loop
    // If a friend request is found to be pending, it will cause a button to
    // appear, allowing you to accept the friend request
    // For later implementation, this can be refined
    // For example: It can cause the notification area to show that you have
    // a friend request pending
    // Also, the ability to deny friend requests is already built in. I'll
    // actually code that in when it become relevant
    // -- Aaron
    Thread friendRequestPolling = new Thread() {
        public void run() {
            while (true) {
                try {
                    sleep(4000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    ParseUser user = ParseUser.getCurrentUser();
                    ParseQuery<ParseObject> friendQuery = ParseQuery
                            .getQuery("FriendRequests");
                    friendQuery.whereEqualTo("Recipient", user);
                    friendQuery
                            .getFirstInBackground(new GetCallback<ParseObject>() {
                                public void done(ParseObject request,
                                        ParseException e) {
                                    if (request != null) {
                                        fReq.setImageResource(R.drawable.friendrequesttrue);
                                    } else {
                                        fReq.setImageResource(R.drawable.friendrequest);
                                    }
                                }
                            });
                }
            }
        }// public void run()
    }; // new Thread()
    friendRequestPolling.start();
    Thread friendAcceptedPolling = new Thread() {
        public void run() {
            while (true) {
                try {
                    sleep(4000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    ParseUser user = ParseUser.getCurrentUser();
                    ParseQuery<ParseObject> friendQuery = ParseQuery
                            .getQuery("FriendRequests");
                    friendQuery.whereEqualTo("Sender", user);
                    friendQuery.whereEqualTo("Accepted", "true");
                    friendQuery
                            .findInBackground(new FindCallback<ParseObject>() {
                                public void done(
                                        List<ParseObject> returnedUsers,
                                        ParseException e) {
                                    for (ParseObject currentUser : returnedUsers) {
                                        if (currentUser != null) {
                                            ParseUser user = ParseUser
                                                    .getCurrentUser();
                                            ParseRelation<ParseUser> relation = user
                                                    .getRelation("friends");
                                            relation.add(currentUser
                                                    .getParseUser("Recipient"));
                                            user.saveInBackground();
                                            currentUser
                                                    .deleteInBackground();
                                        }
                                    }
                                }
                            });
                }
            }
        }// public void run()
    }; // new Thread()
    friendAcceptedPolling.start();
    mPost.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            Intent i = new Intent(GruntrMain.this, MakePost.class);
            startActivity(i);
        }
    });
    addF.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            Intent i = new Intent(GruntrMain.this, AddFriend.class);
            startActivity(i);
        }
    });
    fReq.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            Intent i = new Intent(GruntrMain.this, FriendRequests.class);
            startActivity(i);
        }
    });
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == LOGIN_REQUEST) {
        if (resultCode == RESULT_OK) {
            Intent i = new Intent(GruntrMain.this, GruntrMain.class);
            i.putExtra("User", ParseUser.getCurrentUser().getString("name"));
            startActivity(i);
            finish();
        } else {
            Intent i = new Intent(GruntrMain.this, Goodbye.class);
            startActivity(i);
            finish();
        }
    }
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main_menu, menu);
    return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    } else if (id == R.id.action_logout) {
        ParseUser.logOut();
        ParseUser currentUser = ParseUser.getCurrentUser();
        ParseLoginBuilder builder = new ParseLoginBuilder(GruntrMain.this);
        Intent parseLoginIntent = builder
                .setAppLogo(R.drawable.orangebanner)
                .setParseLoginEnabled(true)
                .setParseLoginButtonText("Go")
                .setParseSignupButtonText("Register")
                .setParseLoginHelpText("Forgot password?")
                .setParseLoginInvalidCredentialsToastText(
                        "Your email and/or password is not correct")
                .setParseLoginEmailAsUsername(true)
                .setParseSignupSubmitButtonText("Submit registration")
                .build();
        startActivityForResult(parseLoginIntent, 0);
    } else if (id == R.id.action_post) {
        Intent i = new Intent(GruntrMain.this, MakePost.class);
        startActivity(i);
    }
    return super.onOptionsItemSelected(item);
}
public void displayGruntList(View view) {
    TextView objectID = (TextView) findViewById(R.id.tvPostIDCheese);
    String id = objectID.getText().toString();
    // String id =
    // ((TextView)(view.findViewById(R.id.tvPostIDCheese))).getText().toString();
    Intent i = new Intent(GruntrMain.this, GruntList.class);
    Bundle idData = new Bundle();
    idData.putString("id", id);
    i.putExtras(idData);
    startActivity(i);
}
public void gruntAtIt(View view) {
    TextView objectID = (TextView) findViewById(R.id.tvPostIDCheese);
    String id = objectID.getText().toString();
    ParseQuery<ParseObject> query = new ParseQuery<ParseObject>("Post");
    query.whereEqualTo("objectId", id);
    ParseObject post = null;
    try {
        post = query.getFirst();
    } catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } finally {
        if (post != null) {
            post.increment("Grunts");
            post.saveInBackground();
        }
    }
    Intent i = new Intent(GruntrMain.this, RecordGrunt.class);
    Bundle idData = new Bundle();
    idData.putString("id", id);
    i.putExtras(idData);
    startActivity(i);
}
}

下面是 CustomAdapter.java,其中进行查询并填充列表。

package com.snowflakes.gruntr;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.parse.ParseFile;
import com.parse.ParseImageView;
import com.parse.ParseObject;
import com.parse.ParseQuery;
import com.parse.ParseQueryAdapter;
import com.parse.ParseRelation;
import com.parse.ParseUser;
public class CustomAdapter extends ParseQueryAdapter<ParseObject> {

public CustomAdapter(Context context) {
    // Use the QueryFactory to construct a PQA that will only show
    // Todos marked as high-pri
    super(context, new ParseQueryAdapter.QueryFactory<ParseObject>() {
        public ParseQuery create() {
            ParseUser user = ParseUser.getCurrentUser();
            ParseRelation<ParseUser> relation = user.getRelation("friends");
            ParseQuery friendsQuery = relation.getQuery();
            ParseQuery<ParseObject> query = new ParseQuery<ParseObject>("Post");
            query.whereMatchesQuery("CreatedBy", friendsQuery);
            query.addDescendingOrder("createdAt");
            return query;
        }
    });
}
// Customize the layout by overriding getItemView
@Override
public View getItemView(ParseObject object, View v, ViewGroup parent) {
    if (v == null) {
        v = View.inflate(getContext(), R.layout.individual_post, null);
    }
    super.getItemView(object, v, parent);
    // Add and download the image
    ParseImageView todoImage = (ParseImageView) v.findViewById(R.id.icon);
    ParseFile imageFile = object.getParseFile("Image");
    if (imageFile != null) {
        todoImage.setParseFile(imageFile);
        todoImage.loadInBackground();
    }
    // Add the title view
    TextView titleTextView = (TextView) v.findViewById(R.id.text1);
    titleTextView.setText(object.get("Name").toString());
    // Add a reminder of how long this item has been outstanding
    TextView timestampView = (TextView) v.findViewById(R.id.timestamp);
    timestampView.setText(object.getCreatedAt().toString());
    TextView objectID = (TextView) v.findViewById(R.id.tvPostIDCheese);
    objectID.setText(object.getObjectId());
    TextView gruntCount = (TextView) v.findViewById(R.id.showGrunts);
    gruntCount.setText("Show Grunts (" + object.getNumber("Grunts") + ")");

    return v;
}

}

传递给 onClick 的视图参数只是单击的视图,而不是周围的布局。除非tvPostIDCheese是按钮的子视图,否则无法以这种方式访问它。

相反,请尝试在适配器的 getItemView 期间使用gruntCount.setTag(object.getObjectId())将对象 ID 存储在可单击的视图中。 然后在displayGruntList中用(String)view.getTag()检索它。

有关进一步的参考,请参阅 setTag 和 getTag。

最新更新