Java 为什么一个sceanrio会出现空指针异常,而不是一个类似的sceanrio?
我感到困惑的是,两种类似的情况都可以描述为:- 在具有ListView的活动中,我单击一个项目,该项目将启动另一个活动来编辑该项目。在第二个活动中,编辑项目并将更改保存到数据库后,我需要通过交换光标来刷新ListView 在一个示例中,我使用了以下内容(这在没有空指针的情况下工作):-Java 为什么一个sceanrio会出现空指针异常,而不是一个类似的sceanrio?,java,android,listview,Java,Android,Listview,我感到困惑的是,两种类似的情况都可以描述为:- 在具有ListView的活动中,我单击一个项目,该项目将启动另一个活动来编辑该项目。在第二个活动中,编辑项目并将更改保存到数据库后,我需要通过交换光标来刷新ListView 在一个示例中,我使用了以下内容(这在没有空指针的情况下工作):- 上面的代码位于名为ProductUsageEdit的活动中,该活动使用activity\u productusage\u edit.xml,并将此设置为ContentView ListViewaaptslv10
- 上面的代码位于名为ProductUsageEdit的活动中,该活动使用activity\u productusage\u edit.xml,并将此设置为ContentView
- ListViewaaptslv100位于activity\u shop\u add.xml中定义的aapts\u布局中activityaddproducttospactivity将aapts\u布局设置为内容视图。单击ListViewaaptslv100中的项目时,此活动将启动ProductUsageEdit活动
- R.id.aapts_布局是主布局的id,R.id.aaptslv100是该布局中ListView的id。此代码通过按钮的OnClickListener调用
View v = findViewById(R.id.aslbc_layout);
ListView callerListView = (ListView) v.findViewById(R.id.aslbclv01);
....
而是在第二个sceanrio中,为了不获取空指针异常,我编写了以下代码:-
Cursor csr = shopperdb.getShopsAsCursor();
ListView callerListView = (ListView) findViewById(R.id.aslbclv01);
ShopsCursorAdapter calleradapter = (ShopsCursorAdapter)callerListView.getAdapter();
calleradapter.changeCursor(csr);
- 上面的代码位于ShopAddActivity中,在布局aslbc\u布局中使用ListViewaslbclv01来自活动shopListByCursor活动
(新增) 再想一想,这两种情况是不同的 第一个sceanrio称为次要活动,其布局更为复杂。因为它是一个带有嵌套线性布局的线性布局,然后是文本/编辑视图 第二个场景使用RelativeLayout,视图都位于该场景下 这可能是获取原始布局ID的需要吗
然而,如果是这样的话,我仍然会思考为什么
View v=findViewById()
在不太复杂的第二个场景中将v设置为null。也许findByView对视图类型敏感?要成功地按id查找视图实例,首先必须确保为活动/片段实例设置了正确的布局<活动AFAIK的code>findViewById()
查找与给定id具有相同id的顶级父节点的子视图。它不会在嵌套的ViewGroup
中递归查找视图<代码>视图组
是视图的后代,充当一个或多个视图的容器LinearLayout
和RelativeLayout
是视图组的几个示例
因此,如果您有以下布局:
res/layout/activity_main.xml
然后,您可以通过调用Activity的findViewById()
成功地获取按钮
实例
Button abutton = (Button) findViewById(R.id.btn_start);
但是,如果您有嵌套布局,例如
res/layout/activity_main2.xml
要正确获取按钮
实例,您必须首先找到按钮的父节点,然后使用它来查找视图
setContentView(R.layout.activity_main2);
View button_container = findViewById(R.id.button_container);
Button abutton = (Button) button_container.findViewById(R.id.btn_start);
在多次尝试获取ListView的适配器后(对于swapCursor()
、changeCursor()
或notifyDataSetChanged()
是必需的)。这包括尝试通过Intent传递对象(序列化问题)。我尝试了onResume,并用一个标志指示触发onResume的原因。因此,至少就目前而言,尝试检索另一个活动的布局元素对于我的经验水平来说太难了
对于第一个场景(将查看第二个和其他场景)
我的最终准则(至少大部分准则)是:-
在更新数据的辅助活动中根本没有代码(关于交换游标)
在调用第二个活动的主活动中:-
public final static int RESUMESTATE_NOTHING = 0;
public final static int RESUMESTATE_PRODUCTUSAGEEDIT = 1;
public final static String[] RESUMESTATE_DESCRIPTIONS = {"Nothing","ProductUsageEdit"};
public int resume_state = RESUMESTATE_NOTHING;
public long currentshopid = -1;
public long currentaisleid = -1;
public ProductsPerAisleCursorAdapter currentppaca;
protected void onResume() {
super.onResume();
Log.i(Constants.LOG," onResume invoked in " + THIS_ACTIVITY + "- Current State=" + resume_state + "-"+RESUMESTATE_DESCRIPTIONS[resume_state]);
switch (resume_state) {
case RESUMESTATE_NOTHING: {
break;
}
case RESUMESTATE_PRODUCTUSAGEEDIT: {
Cursor csr = shopperdb.getProductsperAisle(currentaisleid);
currentppaca.swapCursor(csr);
resume_state = RESUMESTATE_NOTHING;
break;
}
}
}
在调用secondactivity的相应onClickListener中使用以下命令:-
resume_state = RESUMESTATE_PRODUCTUSAGEEDIT;
currentppaca = adapterpl;
currentaisleid = aisleid;
currentshopid = shopid;
您是否尝试过notifyDataSetChanged()方法而不是交换光标?@Nolly J我以前也尝试过,不过我更喜欢交换光标。问题不在于正在更新的ListView,而是它正在发生(即使存在空指针异常)。问题在于方法/技术,可能是对视图范围的更深入理解,也可能是xml资源的一部分(我认为无论如何),这是一个非常好的描述。然而,第二种情况似乎与此相矛盾。除非亲戚(兄弟姐妹)参与进来。也就是说,在第二个场景中,ContentView与视图实例位于不同的活动/类中的视图不相同(在第一个场景中也不相同)。这有点像您如何从main2活动中找到main的按钮(假设您没有找到)。然而,在我的第二个场景中,较短的Viewgroup less FindViewByID可以跨活动工作。我将把问题改为包括活动名称和布局源。
<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" >
<RelativeLayout
android:id="@+id/button_container"
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" >
<Button
android:id="@+id/btn_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/str_btn1" />
</RelativeLayout>
</RelativeLayout>
setContentView(R.layout.activity_main2);
Button abutton = (Button) findViewById(R.id.btn_start);
setContentView(R.layout.activity_main2);
View button_container = findViewById(R.id.button_container);
Button abutton = (Button) button_container.findViewById(R.id.btn_start);
public final static int RESUMESTATE_NOTHING = 0;
public final static int RESUMESTATE_PRODUCTUSAGEEDIT = 1;
public final static String[] RESUMESTATE_DESCRIPTIONS = {"Nothing","ProductUsageEdit"};
public int resume_state = RESUMESTATE_NOTHING;
public long currentshopid = -1;
public long currentaisleid = -1;
public ProductsPerAisleCursorAdapter currentppaca;
protected void onResume() {
super.onResume();
Log.i(Constants.LOG," onResume invoked in " + THIS_ACTIVITY + "- Current State=" + resume_state + "-"+RESUMESTATE_DESCRIPTIONS[resume_state]);
switch (resume_state) {
case RESUMESTATE_NOTHING: {
break;
}
case RESUMESTATE_PRODUCTUSAGEEDIT: {
Cursor csr = shopperdb.getProductsperAisle(currentaisleid);
currentppaca.swapCursor(csr);
resume_state = RESUMESTATE_NOTHING;
break;
}
}
}
resume_state = RESUMESTATE_PRODUCTUSAGEEDIT;
currentppaca = adapterpl;
currentaisleid = aisleid;
currentshopid = shopid;