草庐IT

startActivityForResult() 被弃用,来试试Activity Result API

啵唧脆 2023-06-07 原文

startActivityForResult被弃用,来试试Activity Result API

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

​ 效果图是这样子滴

​ 了解到大家原来都已经用起了Activity Result API,今天把它拿下!

​ 先来回顾一下startActivityForResult的使用

startActivityForResult()的使用

1. 通过startActivityForResult()在MainAcitivity向SecondActivity请求数据

Intent intent1 = new Intent(MainActivity.this, SecondActivity.class);
intent1.putExtra("come","来自活动一的数据");//给SecondActivity传送数据
startActivityForResult(intent1, 1);//向SecondActivity请求数据,并且进行跳转

2. 在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();

3. 在MainActivity的在onActivityResult()方法中去解析SecondActivity返回的结果

@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()方法

​ 那这个要怎么用呢

使用Activity Result API

1.在app下的build.gradle中加入依赖:

implementation 'androidx.activity:activity:1.2.0-beta01'
implementation 'androidx.fragment:fragment:1.3.0-beta01'

2.定义协议

在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");
        }
    }

3.注册协议,获取启动器-ActivityResultLauncher

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();
    }
});

4.调用启动器的launch方法开启界面跳转

最后在MainActivity中启动这个启动器

launcher.launch("来自活动一的数据");

SecondActivity中的代码不变,在这里就不贴出来了。

这样就可以实现两个活动的数据传递。

Contract协议说明

在新的ResultAPI中,虽然只是短短三步就可以实现数据传递,但是代码量并没有减少,使用起来每次都要定义Contract协议。好在!Google为开发者们预定义了很多Contract,可以供我们直接使用。

StartActivityForResult()
RequestMultiplePermissions()
RequestPermission()
TakePicturePreview()
TakePicture()
TakeVideo()
PickContact()
CreateDocument()
OpenDocumentTree()
OpenMultipleDocuments()
OpenDocument()
GetMultipleContents()
GetContent()

  • StartActivityForResult: 通用的Contract,不做任何转换,Intent作为输入,ActivityResult作为输出,这也是最常用的一个协定。
  • RequestMultiplePermissions:用于请求一组权限
  • RequestPermission: 用于请求单个权限
  • TakePicturePreview: 调用MediaStore.ACTION_IMAGE_CAPTURE拍照,返回值为Bitmap图片
  • TakePicture: 调用MediaStore.ACTION_IMAGE_CAPTURE拍照,并将图片保存到给定的Uri地址,返回true表示保存成功。
  • TakeVideo: 调用MediaStore.ACTION_VIDEO_CAPTURE 拍摄视频,保存到给定的Uri地址,返回一张缩略图。
  • PickContact: 从通讯录APP获取联系人
  • GetContent: 提示用选择一条内容,返回一个通过ContentResolver#openInputStream(Uri)访问原生数据的Uri地址(content://形式) 。默认情况下,它增加了Intent#CATEGORY_OPENABLE, 返回可以表示流的内容。
  • CreateDocument: 提示用户选择一个文档,返回一个(file:/http:/content:)开头的Uri。
  • OpenMultipleDocuments: 提示用户选择文档(可以选择多个),分别返回它们的Uri,以List的形式。
  • OpenDocumentTree: 提示用户选择一个目录,并返回用户选择的作为一个Uri返回,应用程序可以完全管理返回目录中的文档。

有了这些预定义的Contract,使用起来就方便多啦,不仅可以轻松实现数据传递,还可以进行拍照,选择图片,选择联系人,打开文档等等返回数据的场景。

简化一下预定义的Contract使用吧

1.在MainActivity中定义启动器

在启动器中处理返回的数据,如果在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();
        }
    }
});

2.运行启动器

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

有关startActivityForResult() 被弃用,来试试Activity Result API的更多相关文章

  1. ruby-on-rails - 我更新了 ruby​​ gems,现在到处都收到解析树错误和弃用警告! - 2

    简而言之错误: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

  2. ruby - 有没有办法让 2.4.0 中的 Ruby 弃用警告静音? - 2

    从Ruby2.4.0开始,对于使用某些已弃用的功能,会出现弃用警告。例如,Bignum、Fixnum、TRUE和FALSE都会触发弃用警告。当我修复我的代码时,有相当多的代码我希望它保持沉默,尤其是在Rails中。我该怎么做? 最佳答案 moduleKerneldefsuppress_warningsoriginal_verbosity=$VERBOSE$VERBOSE=nilresult=yield$VERBOSE=original_verbosityreturnresultendend>>X=:foo=>:foo>>X=:bar

  3. ruby-on-rails - 从 gem 生成的静音弃用警告 - 2

    我正在使用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.

  4. ruby-on-rails - Rails group_by 是否已弃用? - 2

    我有一个要分组的数组,“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

  5. ruby-on-rails - 验证事件连接!在 Rails 4 中已弃用,我们应该如何处理该功能? - 2

    我一直在关注这篇文章以与工头一起设置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但是

  6. ruby - 带 compass 的 ruby 弃用警告 - 2

    当我尝试像往常一样在项目上运行“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

  7. ruby-on-rails - Ruby 2.3 safe navigation operator '&. and the ' 之间有什么区别试试!来自 ActiveSupport 的方法? - 2

    Ruby2.3的安全运算符&.和ActiveSupport的try!方法可以互换吗?如果不是,它们之间有什么区别? 最佳答案 一个关键的区别是try!是一个额外的方法调用,而&.不是。我能想到这造成的一个(公认的人为的)差异"1234"&.gsub(/\d/,"a")$&#=>"1234"这并不奇怪-我进行了正则表达式匹配,因此设置了正则表达式全局变量($&是匹配的字符串)。但是如果(在新的irbsession中——这很重要)我这样做"1234".try!(:gsub,/\d+/,"a")$&#=>nil然后正则表达式相关的全局变量

  8. ruby-on-rails - 弃用警告 : Dangerous query method (method whose arguments are used as raw SQL) called with non-attribute argument(s) - 2

    我将我的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

  9. ruby-on-rails - 这种弃用方法如何工作? - 2

    我试图理解这个调用:deprecate:new_record?,:new?它使用了这个弃用方法:defdeprecate(old_method,new_method)class_eval我不太了解这里使用的元编程。但是,这只是别名new_record?方法的另一种方式吗-所以实际上,new_record?仍然可用,但在您使用它时会发出警告?有人愿意解释一下这是如何工作的吗? 最佳答案 好的,所以这里发生的是old_method的所有功能都已被程序员移至new_method。为了使两个名称都指向相同的功能但注意弃用,程序员放入了dep

  10. ruby-on-rails - Ruby 2.4.1 - 警告:constant::Fixnum 已弃用 - 2

    这个问题在这里已经有了答案:Ruby2.4andRails4stackleveltoodeep(SystemStackError)(3个答案)关闭5年前。我是StackOverflow和Rails的新手,所以我希望这不是一个太幼稚的问题。我正在尝试使用bin/rails服务器在本地运行我的应用程序。当我输入时,我收到以下跟踪信息:=>BootingPuma=>Rails4.2.5applicationstartingindevelopmentonhttp://localhost:3000=>Run`railsserver-h`formorestartupoptions=>Ctrl-Ct

随机推荐