[英]Android - getListView and setListAdapter error with NullPointerException when using custom layout
I have a layout like this 我有这样的布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff">
<com.ftni.core.ui.ActionBar
android:id="@+id/actionbar"
style="@style/ActionBar"/>
<TextView android:id="@+id/list_title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Title"
android:textStyle="bold"
android:textColor="#000000"
android:textSize="18sp"
android:padding="3px"/>
<ListView android:id="@id/android:list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:drawSelectorOnTop="false"/>
</LinearLayout>
and in my listview (code that was working before I changed the layout) 并在我的列表视图中(更改布局之前有效的代码)
private void buildListView()
{
ListView lv = getListView();
registerForContextMenu(lv);
lv.setTextFilterEnabled(true);
lv.clearChoices();
setListAdapter(new UserListAdapter(SuspendedUsersActivity.this, R.layout.useritem, users));
lv.setOnItemClickListener(clickListener);
}
I tried moving the call to setListAdapter
first, but I still get the NullPointerException. 我尝试先将调用移到
setListAdapter
,但仍然收到NullPointerException。 Here's the logcat 这是logcat
FATAL EXCEPTION: main
java.lang.NullPointerException
at android.app.ListActivity.setListAdapter(ListActivity.java:267)
at com.myapp.backoffice.users.SuspendedUsersActivity.buildListView(SuspendedUsersActivity.java:140)
at com.myapp.backoffice.users.SuspendedUsersActivity.access$0(SuspendedUsersActivity.java:138)
at com.myapp.backoffice.users.SuspendedUsersActivity$2.handleMessage(SuspendedUsersActivity.java:194)
at android.os.Handler.dispatchMessage(Handler.java:99)
I have a feeling that what is happening is that the default ID I was told is correct ( @id/android:list
) is not correct for the default list view. 我感觉正在发生的事情是,我被告知的默认ID是正确的(
@id/android:list
)对于默认列表视图而言是不正确的。
EDIT: 编辑:
Here are more details about how I have this set up. 以下是有关如何进行此设置的更多详细信息。
First, I have an inherited activity to ensure the user is authenticated. 首先,我有一个继承的活动,以确保对用户进行身份验证。 When I inherit directly from this class, all works fine.
当我直接从此类继承时,一切正常。
public class ProtectedListActivity extends ListActivityBase {
boolean isAuthenticated = false;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Thread validationThread = new Thread()
{
@Override
public void run()
{
try
{
isAuthenticated = UserService.ValidateToken();
}
catch (FTNIServiceException e)
{
//eat it
}
finally
{
if (!isAuthenticated)
{
startActivity(new Intent(ProtectedListActivity.this, SignInActivity.class));
finish();
}
}
}
};
validationThread.start();
}
}
Then, I extend that one step further to wrap my default action bar setup into a base class. 然后,我将这一步骤进一步扩展到将我的默认操作栏设置包装到基类中。
public class ListWithActionBarActivity extends ProtectedListActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void onContentChanged()
{
ActionBar actionBar = (ActionBar)findViewById(R.id.actionbar);
if (actionBar != null)
{
actionBar.setOnTitleClickListener(new OnClickListener() {
public void onClick(View v) {
startActivity(new Intent(ListWithActionBarActivity.this, SelectSiteActivity.class));
finish();
}
});
SiteModel site = PreferencesHelper.getSite();
actionBar.setTitle(site.Name + " (" + site.Abbreviation + ")");
actionBar.addAction(new IntentAction(ListWithActionBarActivity.this,
new Intent(ListWithActionBarActivity.this, MainMenuActivity.class),
R.drawable.ic_title_home_default));
}
}
public static Intent createIntent(Context context) {
Intent i = new Intent(context, MainMenuActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
return i;
}
protected Intent createShareIntent() {
final Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, "Shared from the ActionBar widget.");
return Intent.createChooser(intent, "Share");
}
}
Then, because I have 2 lists of users separated by status (suspended or active) I was attempting to wrap an addition to the action bar in a base class. 然后,因为我有2个按状态(挂起或活动)分开的用户列表,所以我试图将附加的操作包装到基类中。
public class UserBase extends ListWithActionBarActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
//setContentView(R.layout.queue);
super.onCreate(savedInstanceState);
ActionBar actionBar = (ActionBar)findViewById(R.id.actionbar);
actionBar.addAction(new UserStatusSelectorAction(UserBase.this));
}
}
and finally, we have my activity. 最后,我们有我的活动。 I've omitted a little code, but I left most of it so you could see how the data is retrieved through another thread while a loading screen is shown, and then the listview is built.
我省略了一些代码,但是我保留了大部分代码,因此您可以看到在显示加载屏幕时如何通过另一个线程检索数据,然后构建了listview。
public class SuspendedUsersActivity extends ListWithActionBarActivity implements Runnable{
ProgressDialog progress;
ArrayList<UserModel> users;
int position;
@Override
public void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.queue);
super.onCreate(savedInstanceState);
TextView title = (TextView)findViewById(R.id.list_title);
title.setText("Suspended Users");
progress = ProgressDialog.show(SuspendedUsersActivity.this, "", "Loading...", true);
Thread thread = new Thread(SuspendedUsersActivity.this);
thread.start();
}
private void buildListView()
{
ListView lv = getListView();
//registerForContextMenu(lv);
lv.setTextFilterEnabled(true);
lv.clearChoices();
setListAdapter(new UserListAdapter(SuspendedUsersActivity.this, R.layout.useritem, users));
lv.setOnItemClickListener(clickListener);
}
private OnItemClickListener clickListener = new OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
UserModel user = users.get(position);
SuspendedUserAction action = new SuspendedUserAction(SuspendedUsersActivity.this, user.UserId);
action.performAction(view);
}
};
@Override
public void run() {
// TODO Auto-generated method stub
SiteModel site = PreferencesHelper.getSite();
try
{
users = UserService.GetSuspendedUsers(site.SiteId);
}
catch (FTNIServiceException e)
{
// TODO Auto-generated catch block
Message message = new Message();
message.what = ActivityBase.RESULT_ERROR;
message.obj = e.getMessage();
handler.sendMessage(message);
return;
}
handler.sendEmptyMessage(ActivityBase.RESULT_DONE);
}
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch(msg.what)
{
case ActivityBase.RESULT_SUCCESS:
progress.dismiss();
startActivity(new Intent(SuspendedUsersActivity.this, SelectSiteActivity.class));
finish();
break;
case ActivityBase.RESULT_DONE:
buildListView();
ApplicationController app = (ApplicationController)getApplication();
app.setSuspendedUsersChanged(false);
progress.dismiss();
break;
case ActivityBase.RESULT_ERROR:
progress.dismiss();
new AlertDialog.Builder(SuspendedUsersActivity.this)
.setMessage(msg.obj.toString())
.setNeutralButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
//do nothing
arg0.dismiss();
}
})
.show();
break;
}
}
};
}
It works with ProtectedListActivity when I do not set a content view, but everything else it fails on, whether or not I set the content view and comment out the actionbar stuff. 当我未设置内容视图时,它可以与ProtectedListActivity一起使用,但是无论是否设置内容视图并注释掉操作栏内容,它都会失败。
your must extends MainActivity
to ListActivity
. 您必须将
MainActivity
扩展到ListActivity
。
public class MainActivity extends ListActivity {
}
Probably you are not setting the value to the ListView global variable. 可能您没有将值设置为ListView全局变量。
Post getListView() code to more help. 发布getListView()代码以获取更多帮助。
The NPE is thrown on NPE被抛出
setListAdapter(new UserListAdapter(SuspendedUsersActivity.this, R.layout.useritem,
users));
so the users variable is most likely null. 因此users变量很可能为null。
Set a breakpoint right after the line ListView lv = getListView();
在
ListView lv = getListView();
行后立即设置一个断点ListView lv = getListView();
Chances are this is giving you a null value. 可能这会给您一个空值。
Honestly I would try to go with a regular activity and just configure the ListView manually. 老实说,我会尝试进行常规活动,而只是手动配置ListView。 It isn't hard and it seems like a better way to support having two lists in one Activity.
这并不难,并且似乎是在一个Activity中支持两个列表的更好方法。
I changed the listview to explicitly give it an id like this 我将listview更改为明确给它一个这样的ID
<ListView android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:drawSelectorOnTop="false"/>
And then I changed my code to this 然后我将代码更改为此
private void buildListView()
{
ListView lv = (ListView)findViewById(R.id.list_view);
lv.setTextFilterEnabled(true);
lv.clearChoices();
lv.setAdapter(new UserListAdapter(SuspendedUsersActivity.this, R.layout.useritem, users));
lv.setOnItemClickListener(clickListener);
}
And now it works. 现在就可以了。 For some reason that default ID for the listview doesn't work.
由于某种原因,列表视图的默认ID不起作用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.