startActivityForResult被弃用,来试试Activity Result API
startActivityForResult()用于两个活动之间交换信息,今天用到的时候发现这个方法已经被弃用了。

效果图是这样子滴
了解到大家原来都已经用起了Activity Result API,今天把它拿下!
先来回顾一下startActivityForResult的使用
Intent intent1 = new Intent(MainActivity.this, SecondActivity.class);
intent1.putExtra("come","来自活动一的数据");//给SecondActivity传送数据
startActivityForResult(intent1, 1);//向SecondActivity请求数据,并且进行跳转
通过getIntent()和getStringExtra获得来自MainActivity的数据,实现两个活动的交流。
Intent intent = getIntent();
String s = intent.getStringExtra("come");
用setResult()方法设置要返回给MainActivity的数据。
Intent intent2 = new Intent(SecondActivity.this, MainActivity.class);
intent2.putExtra("return", "活动二返回的数据");
setResult(RESULT_OK, intent2);
finish();
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
switch (requestCode) {
case 1:
if (resultCode == RESULT_OK) {
String returnedDate = data.getStringExtra("return");
Log.e(TAG, returnedDate);
}
break;
default:
}
super.onActivityResult(requestCode, resultCode, data);
}
看得出来确实,一旦活动和数据多一些,onActivityResult就会变得臃肿耦合,resultcode也要不断进行扩充定义。
现在官方推荐使用Activity Result API代替startActivityForResult()方法
那这个要怎么用呢
implementation 'androidx.activity:activity:1.2.0-beta01'
implementation 'androidx.fragment:fragment:1.3.0-beta01'
在MainAcitivity中新建一个 ResultContract类继承于ActivityResultContract<I,O>,I是输入的数据类型,O是输出的数据类型。在下面的例子里两个活动的数据都定义为String。
我们在createIntent的方法里放入MainActivity传送给SecondActivity的数据,在parseResult里取出SecondActivity传回来的数据。
class ResultContract extends ActivityResultContract<String, String> {
@NonNull
@Override
public Intent createIntent(@NonNull Context context, String input) {
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
intent.putExtra("come", input);
return intent;
}
@Override
public String parseResult(int resultCode, @Nullable Intent intent) {
return intent.getStringExtra("return");
}
}
registerForActivityResult有两个参数第一个参数就是我们定义的Contract协议,第二个参数是一个回调ActivityResultCallback,其中O就是前面Contract的输出类型。
在启动器中我们获取了返回的数据并且进行了展示。
ActivityResultLauncher launcher = registerForActivityResult(new ResultContract(), new ActivityResultCallback<String>() {
@Override
public void onActivityResult(String result) {
Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();
}
});
最后在MainActivity中启动这个启动器
launcher.launch("来自活动一的数据");
SecondActivity中的代码不变,在这里就不贴出来了。
这样就可以实现两个活动的数据传递。
在新的ResultAPI中,虽然只是短短三步就可以实现数据传递,但是代码量并没有减少,使用起来每次都要定义Contract协议。好在!Google为开发者们预定义了很多Contract,可以供我们直接使用。
StartActivityForResult()
RequestMultiplePermissions()
RequestPermission()
TakePicturePreview()
TakePicture()
TakeVideo()
PickContact()
CreateDocument()
OpenDocumentTree()
OpenMultipleDocuments()
OpenDocument()
GetMultipleContents()
GetContent()
有了这些预定义的Contract,使用起来就方便多啦,不仅可以轻松实现数据传递,还可以进行拍照,选择图片,选择联系人,打开文档等等返回数据的场景。
在启动器中处理返回的数据,如果在SecondAcitivity中设置的result不为空并且resultcode为ok,则对数据进行处理。
ActivityResultLauncher<Intent> intentActivityResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
//此处是跳转的result回调方法
//如果在SecondAcitivity中设置的result不为空并且resultcode为ok,则对数据进行处理
if (result.getData() != null && result.getResultCode() == Activity.RESULT_OK) {
String msg = result.getData().getStringExtra("return");
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(), "获取的数据为空", Toast.LENGTH_LONG).show();
}
}
});
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
intent.putExtra("come","来自活动一的数据");
intentActivityResultLauncher.launch(intent);
}
});
就可以啦!!!
吼吼吼!这样看来真的很方便,但还是摸索了一个下午QAQ,网上大多数资料都是kotlin版本的,惭愧残惭愧,还没学习kotlin。
总的来说,有了官方预定义的Contract确实对于很多数据回调的场景提供了便利,也可以自己自定义一个新的contract,具有一定的灵活性,真不戳!
期待下一次更深层次的挖掘。先这样吧,俺累了。
参考资料:
https://mp.weixin.qq.com/s/lWayiBS4T4EHcsUIgnhJzA
https://guolin.blog.csdn.net/article/details/121063078?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-121063078-blog-125336554.pc_relevant_aa&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-121063078-blog-125336554.pc_relevant_aa&utm_relevant_index=1
简而言之错误:NOTE:Gem::SourceIndex#add_specisdeprecated,useSpecification.add_spec.Itwillberemovedonorafter2011-11-01.Gem::SourceIndex#add_speccalledfrom/opt/local/lib/ruby/site_ruby/1.8/rubygems/source_index.rb:91./opt/local/lib/ruby/gems/1.8/gems/rails-2.3.8/lib/rails/gem_dependency.rb:275:in`==':und
从Ruby2.4.0开始,对于使用某些已弃用的功能,会出现弃用警告。例如,Bignum、Fixnum、TRUE和FALSE都会触发弃用警告。当我修复我的代码时,有相当多的代码我希望它保持沉默,尤其是在Rails中。我该怎么做? 最佳答案 moduleKerneldefsuppress_warningsoriginal_verbosity=$VERBOSE$VERBOSE=nilresult=yield$VERBOSE=original_verbosityreturnresultendend>>X=:foo=>:foo>>X=:bar
我正在使用unscoped_associations我的Rails5.0.0.1应用程序中的gem。我收到这个弃用警告:DEPRECATIONWARNING:alias_method_chainisdeprecated.Please,useModule#prependinstead.Frommodule,youcanaccesstheoriginalmethodusingsuper.(calledfromat/home/rhl/myapp/config/application.rb:8)DEPRECATIONWARNING:alias_method_chainisdeprecated.
我有一个要分组的数组,“group_by”函数似乎适合我的情况。http://apidock.com/rails/Enumerable/group_by我在Rails3.2.13中使用它。grouped_array=my_array.group_by(&:my_function)#Assumerun'my_function'haveresult1onelement1,element3andresult2onelement2,element4,then:#grouped_array={#result1=>[element1,element3],#result2=>[element2,el
我一直在关注这篇文章以与工头一起设置puma:https://www.digitalocean.com/community/articles/how-to-set-up-zero-downtime-rails-deploys-using-puma-and-foremanpuma脚本在连接后告诉verify_active_connections!但它在rails4中不可用。注释掉方法调用将使脚本运行但我不确定这是否会泄漏资源.关于这个问题,我能看到的唯一文档是:https://github.com/socialcast/resque-ensure-connected/issues/3但是
当我尝试像往常一样在项目上运行“bundleexeccompasswatch”时,我现在收到此警告:DEPRECATIONWARNINGonline87of/home/hedy/Sites/mywebsite.fr/src/vendor/bundle/ruby/2.3.0/gems/compass-core-1.0.3/stylesheets/compass/css3/_deprecated-support.scss:#{}interpolationnearoperatorswillbesimplifiedinafutureversionofSass.Topreservethecurr
Ruby2.3的安全运算符&.和ActiveSupport的try!方法可以互换吗?如果不是,它们之间有什么区别? 最佳答案 一个关键的区别是try!是一个额外的方法调用,而&.不是。我能想到这造成的一个(公认的人为的)差异"1234"&.gsub(/\d/,"a")$=>"1234"这并不奇怪-我进行了正则表达式匹配,因此设置了正则表达式全局变量($&是匹配的字符串)。但是如果(在新的irbsession中——这很重要)我这样做"1234".try!(:gsub,/\d+/,"a")$=>nil然后正则表达式相关的全局变量
我将我的Rails5.1.4应用更新到了5.2.0。我的一个模型中有以下范围:scope:by_category,lambda{|category_slug|category_ids=Category.find_by(slug:category_slug)&.subtree_idswhere(category_id:category_ids)}由于该范围,Rails返回以下错误:DEPRECATIONWARNING:Dangerousquerymethod(methodwhoseargumentsareusedasrawSQL)calledwithnon-attributeargume
我试图理解这个调用:deprecate:new_record?,:new?它使用了这个弃用方法:defdeprecate(old_method,new_method)class_eval我不太了解这里使用的元编程。但是,这只是别名new_record?方法的另一种方式吗-所以实际上,new_record?仍然可用,但在您使用它时会发出警告?有人愿意解释一下这是如何工作的吗? 最佳答案 好的,所以这里发生的是old_method的所有功能都已被程序员移至new_method。为了使两个名称都指向相同的功能但注意弃用,程序员放入了dep
这个问题在这里已经有了答案:Ruby2.4andRails4stackleveltoodeep(SystemStackError)(3个答案)关闭5年前。我是StackOverflow和Rails的新手,所以我希望这不是一个太幼稚的问题。我正在尝试使用bin/rails服务器在本地运行我的应用程序。当我输入时,我收到以下跟踪信息:=>BootingPuma=>Rails4.2.5applicationstartingindevelopmentonhttp://localhost:3000=>Run`railsserver-h`formorestartupoptions=>Ctrl-Ct