startActivityForResult中回调setResult注意事项

读 http://www.cnblogs.com/lijunamneg/archive/2013/02/05/2892616.html 有感

文中提出了一个核心问题:

Android activity的setResult()在什么时候调用?

他给出了答案:

activity返回result是在被finish的时候,也就是说调用setResult()方法必须在finish()之前。
那么如果在如下方法中调用setResult()也有可能不会返回成功: onPause(), onStop(), onDestroy(),
因为这些方法调用不一定是在finish之前的,当然在onCreate()就调用setResult肯定是在finish之前的

什么意思呢:

假设我们有MainActivity和SecondActivity来一次跳转。

package com.example.setresult;

import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.os.Build;

public class MainActivity extends ActionBarActivity {

    private final static String TAG = MainActivity.class.getSimpleName();

	final int   requestCode=1;
	Button b1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        b1=(Button)findViewById(R.id.b1);
        b1.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				startActivityForResult(new Intent(MainActivity.this,SecondActivity.class), requestCode);

			}
		});
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent arg2) {
    	Log.d(TAG, "resultCode="+resultCode);
    	  switch (resultCode) {
          case RESULT_OK:
        	  Log.d(TAG, "ok");
              break;
      }
    	super.onActivityResult(requestCode, resultCode, arg2);
    }

    @Override
    protected void onRestart() {
  	  Log.d(TAG, "MainActivity onRestart");
    	super.onRestart();
    }
    @Override
    protected void onResume() {
    	 Log.d(TAG, "MainActivity onResume");
    	super.onResume();
    }
}

  

package com.example.setresult;

import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.os.Build;

public class SecondActivity extends ActionBarActivity {
    private final static String TAG = SecondActivity.class.getSimpleName();

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_second);
		setResult(RESULT_OK);
	}

	@Override
	protected void onStop() {

	Log.d(TAG, "SecondActivity onStop");
		super.onStop();
	}
	@Override
	protected void onDestroy() {
		Log.d(TAG, "SecondActivity onDestroy");
		super.onDestroy();
	}
	@Override
	public void onBackPressed() {

		Log.d(TAG, "SecondActivity onBackPressed");
		super.onBackPressed();
	}
	@Override
	protected void onStart() {
		Log.d(TAG, "SecondActivity onStart");
		super.onStart();
	}
	@Override
	protected void onPause() {

		Log.d(TAG, "SecondActivity onPause");
		super.onPause();
	}
}

  

07-30 20:15:37.291: D/SecondActivity(30684): SecondActivity onStart
07-30 20:15:39.151: D/SecondActivity(30684): SecondActivity onBackPressed

07-30 20:25:18.531: D/SecondActivity(32594): SecondActivity onPause

07-30 20:15:39.161: D/MainActivity(30684): resultCode=-1
07-30 20:15:39.161: D/MainActivity(30684): RESULT_OK
07-30 20:15:39.161: D/MainActivity(30684): MainActivity onRestart
07-30 20:15:39.161: D/MainActivity(30684): MainActivity onResume
07-30 20:15:39.501: D/SecondActivity(30684): SecondActivity onStop
07-30 20:15:39.501: D/SecondActivity(30684): SecondActivity onDestroy

当从SecondActivity按返回键的时候,发生以上日志。可以看见resultCode=-1是正确的

但是当你把

setResult(RESULT_OK);

这句话放到SecondActivity Onstop()中

就会发生以下日志:

07-30 20:19:31.521: D/SecondActivity(31785): SecondActivity onStart
07-30 20:19:35.031: D/SecondActivity(31785): SecondActivity onBackPressed

07-30 20:25:18.531: D/SecondActivity(32594): SecondActivity onPause

07-30 20:19:35.051: D/MainActivity(31785): resultCode=0
07-30 20:19:35.051: D/MainActivity(31785): MainActivity onRestart
07-30 20:19:35.051: D/MainActivity(31785): MainActivity onResume
07-30 20:19:35.381: D/SecondActivity(31785): SecondActivity onStop
07-30 20:19:35.381: D/SecondActivity(31785): SecondActivity onDestroy

resultCode=0 说明setResult没有成功

可见当onBackPressed事件发生后,activity会直接掉finish()方法,这时候resultCode就已经返回给前一个Activity了,所以就得到默认值resultCode=0

由此得出一个结论

setResult()调用必须要在OnPause()之前

时间: 2024-10-27 09:52:16

startActivityForResult中回调setResult注意事项的相关文章

Android 4.4 中 WebView 使用注意事项

Android 4.4 中 WebView 使用注意事项 自Android 4.4起,Android中的WebView开始基于Chromium( 这大概是因为Android部门负责人从Andy Rubin变成了Chrome部门的主管Sundar Pichai了吧,_). 这个改变,使得WebView的性能大幅度提升,并且对HTML5, CSS3, and JavaScript有了更好的支持. 那么,作为一个客户端开发者,我们写代码的时候需要注意哪些呢? 1.多线程 如果你在子线程中调用WebVi

startActivityForResult() 中requestCode 和 resultCode 的作用

startActivityForResult()中 * requestCode 请求码,即调用startActivityForResult() 传递过去的值 * resultCode 结果码,结果码用于标识返回数据来自哪个新Activity 一.实例: 1.在Activity中得到新打开Activity 关闭后返回的数据 startActivityForResult( 第一个参数,第二参数) 第一个参数 : 得到新打开Activity关闭后返回的数据 第二个参数 :为请求码,可以根据业务需求自己

Python 3.X 调用多线程C模块,并在C模块中回调python函数的示例

由于最近在做一个C++面向Python的API封装项目,因此需要用到C扩展Python的相关知识.在此进行简要的总结. 此篇示例分为三部分.第一部分展示了如何用C在Windows中进行多线程编程:第二部分将第一部分的示例进行扩展,展示了如何在python中调用多线程的C模块:第三部分扩展了第二部分,增加了在C模块的线程中回调python的演示. 本文所用的环境为:64位Win7 + python 3.4 x86 + vs2010 一.windows下的C语言多线程程序 windows下多线程编程

AW笔记本升级SSD,外接双屏中的一些注意事项

自己留一个mark,以后提醒用. 1)机械硬盘状态下利用alien sprawn创建的系统恢复U盘,无法在SSD下使用,因为SSD中没有recovery分区,只能使用随机携带的系统恢复光盘: 2)最好在SSD安装系统之前,先用机械硬盘引导,在windows下使用diskgenious进行格式化分区,4k字节对齐: 3)将SSD安装在硬盘盘位1,因为是最经常使用,并在bios中设置SATA option为ACHI: 4)利用恢复光盘进行系统安装,记住选择SSD的分区: 5)系统安装成功后,按照网上

IOS 中NSTimer使用注意事项

1.初始化 + (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo; + (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelec

C++中回调函数(CallBack)的使用

如果试图直接使用C++的成员函数作为回调函数将发生错误,甚至编译就不能通过. 其错误是普通的C++成员函数都隐含了一个传递函数作为参数,亦即“this”指针,C++通过传递this指针给其成员函数从而实现成员函数可以访问C++的数据成员.这也可以理解为什么C++类的多个实例可以共享成员函数却-有不同的数据成员.由于this指针的作用,使得将一个CALL-BACK型的成员函数作为回调函数安装时就会因为隐含的this指针使得函数参数个数不匹配,从而导致回调函数安装失败.要解决这一问题的关键就是不让t

Storm中Spout使用注意事项小结

Storm中Spout用于读取并向计算拓扑中发送数据源,最近在调试一个topology时遇到了系统qps低,处理速度达不到要求的问题,经过排查后发现是由于对Spout的使用模式不当导致的多线程同步等待.这里罗列几点个人觉得编写Spout代码时需要特别注意的地方: 1. 最常用的模式是使用一个线程安全的queue,如BlockingQueue,spout主线程从queue中读取数据:另外的一个或多个线程负责从数据源(如各种消息中间件.db等)读取数据并放入queue中. 2. 如果不关心数据是否丢

关于myBatis配置中的一些注意事项

最近在学习mybatis,在网上查阅资料,并按照别人的范例来测试,总会出一些错误,这里把配置过程中的一些注意事项梳理一下. 一.导包(用eclipse开发) 1.如果你新建的是普通的project,需要在工程目录下,新建一个文件夹(一般为lib),然后需要手动导包,具体操作是:选中包右键-Build Path-add to Build Path.之前的文件夹不能删除,因为它实际上加载的是这些包的路径. 2.如果你新建的是web工程,只需要把相关包放到WEB-INF/lib 中即可,它会自动导包,

关于Array的map方法中回调函数参数的问题

开门见山,我们先来看两个例子. var arr=['1','4','9','16']; var r=arr.map(Math.sqrt); 猜猜r的结果会是多少? 没错就是 [1,2,3,4] 我们再来试试另一个, var arr=['1','4','9','16']; var r=arr.map(parseInt); 再猜猜结果是多少? 是[1,2,3,4]? console试一试看看结果是多少 [1,NaN,NaN,1]! 是不是大吃一惊 其实真相---- 就是参数个数搞的鬼! 让我们再来看