Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.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
Android startActivityForResult的替代方案_Android - Fatal编程技术网

Android startActivityForResult的替代方案

Android startActivityForResult的替代方案,android,Android,编辑:将Fragment更改为Partial,我写这篇文章时不知道Fragment对象 我有一个部分,其中包含一个按钮来打开联系人列表。这样做需要打电话 startActivityForResult( new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI), MY_REQUEST_CODE ); 在我的活动中处理结果,比如: public void onActivityResult( int requestCode, int resultCod

编辑:将Fragment更改为Partial,我写这篇文章时不知道Fragment对象

我有一个部分,其中包含一个按钮来打开联系人列表。这样做需要打电话

startActivityForResult( new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI), MY_REQUEST_CODE );
在我的活动中处理结果,比如:

public void onActivityResult( int requestCode, int resultCode, Intent data ) {
    if (resultCode == RESULT_OK) {
        switch (requestCode) {
            case MY_REQUEST_CODE: {
                Address address = contact_address( data );
                if (address != null) {
                    // do something with address
                }
            } break;
        }
    }
}
根据我在活动布局中如何包含该部分,它可能在其他部分中有好几层,并且可能有多个部分实例

我希望避免将我的\u请求\u代码的ID传播到调用该活动的部分-或其任何变体,如将onClickListener分配给按钮-我不希望顶级UI关心部分是如何构造的


是否有一个标准的方法来实现这一点?在我看来,如果onActivityResult可以接受Uri而不是int代码,那么就可以避免传播。我希望我在这里遗漏了一些明显的东西…

我觉得Commonware的解决方案没有回答我的问题,因为它要求分部的每个容器为完全包含在分部中的事件添加处理程序

我特别不希望必须为该部分的每个实例实现处理程序

所以我想出了一个解决办法,尽管我承认这感觉也不对

首先,我将Activity子类化,并创建一个小框架,用于将侦听器与startActivityForResult()和onActivityResult()关联

然后在部分中,我调用重载的startActivityForResult()并实现一个侦听器:

public void onFinishInflate() {
    ImageButton contact_button = (ImageButton)findViewById(R.id.contact_button);
    contact_button.setOnClickListener( new OnClickListener() {
        @Override
        public void onClick(View view) {
            ((BaseActivity)getContext()).startActivityForResult( new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI), 
                new BaseActivity.ActivityResultListener() {
                    @Override
                    public void onResultCode( int resultCode, Intent data ) {
                        if (resultCode == BaseActivity.RESULT_OK) {
                            add_contact_address( data );
                        }
                    }
                });
        }
    } ); 
}
所以现在我可以到处使用这个部分,而不必为每个实例定义侦听器


我看到的缺点是子类化活动将阻止我使用其他活动类型。这可以被修改成一个接口/实现,但随后又开始遭受非干式逻辑的困扰。

这两种方法都不起作用。当调用活动被系统替换时(例如,通过屏幕旋转),两者都容易出现问题

在Commonware的回答中,requestContact()分配的OnContactPickedListener将引用一个不再存在的控件

在我自己的回答中,活动保留的侦听器将消失,新活动的等效侦听器将为null

然而,有一个解决方案,它依赖于使侦听器的上下文可重新分配

借鉴我以前的解决方案,将ActivityResultListener接口重新构建为一个静态类:

abstract public static class ActivityResultListener {
    private Context
        context_;
    public ActivityResultListener( Context context ) {
        context_ = context;
    }
    public Context getContext() { return context_; }
    public void setContext( Context context ) { context_ = context; }

    abstract public void onResultCode( int resultCode, Intent data );
}
设置内部类以记录BaseActivity的状态:

protected static class BaseState {
    private final ActivityResultListener
        activity_result_listener_;

    protected BaseState( BaseActivity activity ) {
        activity_result_listener_ = activity.activity_result_listener_;
    }

    protected void setState( BaseActivity activity ) {
        activity.activity_result_listener_ = activity_result_listener_;
        if (activity.activity_result_listener_ != null) {
            activity.activity_result_listener_.setContext( activity );
        }
    }
}
@Override
public Object onRetainNonConfigurationInstance() {
    return new BaseState( this );
}
请特别注意setState()中对setContext()的调用。这避免了与非静态接口实现相关的问题,即在重新创建活动时它们的引用消失

从BaseActivity中保留状态:

protected static class BaseState {
    private final ActivityResultListener
        activity_result_listener_;

    protected BaseState( BaseActivity activity ) {
        activity_result_listener_ = activity.activity_result_listener_;
    }

    protected void setState( BaseActivity activity ) {
        activity.activity_result_listener_ = activity_result_listener_;
        if (activity.activity_result_listener_ != null) {
            activity.activity_result_listener_.setContext( activity );
        }
    }
}
@Override
public Object onRetainNonConfigurationInstance() {
    return new BaseState( this );
}
从BaseActivity.onCreate()中恢复状态

在ActivityResultListener的实现中,确保使用getContext()和findViewById()按需取消引用所有内容,而不是存储引用:

private static class ContactChoiceListener extends BaseActivity.ActivityResultListener {
    private final int 
        id_;

    public ContactChoiceListener( Context context, int id ) {
        super( context );
        id_ = id;
    }

    @Override
    public void onResultCode( int resultCode, Intent data ) {
        if (resultCode == BaseActivity.RESULT_OK) {
            AddressEditor editor = (AddressEditor)((BaseActivity)getContext()).findViewById( id_ );
            if (editor != null)
                editor.add_contact_address( data );
        }
    }
}
呼。最好的部分是,这些都过时了,因为片段有一种完全不同的处理状态的方式,使用setRetainInstance(布尔值)

我将很快实现该版本,如果有兴趣,我将在这里发布