Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么一个sceanrio会出现空指针异常,而不是一个类似的sceanrio?_Java_Android_Listview - Fatal编程技术网

Java 为什么一个sceanrio会出现空指针异常,而不是一个类似的sceanrio?

Java 为什么一个sceanrio会出现空指针异常,而不是一个类似的sceanrio?,java,android,listview,Java,Android,Listview,我感到困惑的是,两种类似的情况都可以描述为:- 在具有ListView的活动中,我单击一个项目,该项目将启动另一个活动来编辑该项目。在第二个活动中,编辑项目并将更改保存到数据库后,我需要通过交换光标来刷新ListView 在一个示例中,我使用了以下内容(这在没有空指针的情况下工作):- 上面的代码位于名为ProductUsageEdit的活动中,该活动使用activity\u productusage\u edit.xml,并将此设置为ContentView ListViewaaptslv10

我感到困惑的是,两种类似的情况都可以描述为:-

在具有ListView的活动中,我单击一个项目,该项目将启动另一个活动来编辑该项目。在第二个活动中,编辑项目并将更改保存到数据库后,我需要通过交换光标来刷新ListView

在一个示例中,我使用了以下内容(这在没有空指针的情况下工作):-

  • 上面的代码位于名为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调用

另一种情况是,如果使用等效ie从布局ID获取初始活动的视图,然后通过该V获取ListView的ID;发出nullpointer异常(仍然会刷新ListView),即使用:-

    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活动
(很明显,Listview与使用的适配器和获得的光标不同,ps finish()是在该代码所在的If子句之外稍晚编码的)

如果在第一个场景中尝试使用与此等效的方法,则会出现空指针异常(再次刷新ListView)

我想要的是一个标准的方法,可以同时适用于其他类似的情况。我也非常希望能够理解为什么我需要对基本相同的场景使用不同的方法


(新增)

再想一想,这两种情况是不同的

第一个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;