Android Activity Result API

这篇具有很好参考价值的文章主要介绍了Android Activity Result API。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.Activity Results API

在appcompat库1.3.0或更高的版本中,startActivityForResult()方法被废弃了。这个方法主要是用于在两个Activity之间交换数据的。Google官方建议使用Activity Result API来实现在两个Activity或Fragment之间交换数据、获取返回结果的功能。

Activity Result API主要用到两个组件:

①ActivityResultContract: 协议,它定义了如何传递数据和如何处理返回的数据。

ActivityResultContract是一个抽象类,需要继承它来创建自己的协议,每个 ActivityResultContract都需要定义输出和输入类,如果不需要任何输出,可应用void(在Kotlin中应用Void?或Unit)作为输出类型。

②ActivityResultLauncher: 启动器,调用它的launch方法来启动页面跳转,作用相当于原来的startActivity()。

 文章来源地址https://www.toymoban.com/news/detail-619584.html

2.使用方法

①定义协议

首先自定义一个Contract用于两个activity互传数据处理。自定义Contract需要继承自ActivityResultContract<I,O>,其中I是输入的类型,O是输出的类型,并实现2个方法:createIntent和parseResult,输入类型I作为createIntent方法的参数,输出类型O作为parseResult方法的返回值。

class MyActivityResultContract : ActivityResultContract<String, String?>() { 

    override fun createIntent(context: Context, input: String?): Intent { 

        return Intent(context, SecondActivity::class.java).apply { 

            putExtra("input", input) 

        } 

    } 

    override fun parseResult(resultCode: Int, intent: Intent?): String? { 

        val data = intent?.getStringExtra("result") 

        return if (resultCode == Activity.RESULT_OK && !TextUtils.isEmpty(data)) data else null 

    } 

在createIntent方法中创建Intent,并携带了参数input,在parseResult方法中获取返回的数据result。

②注册协议,获取启动器ActivityResultLauncher

调用registerForActivityResult方法注册刚刚定义的contract协议,该方法由ComponentActivity或Fragment提供,有2个参数,第一个参数是自定义的Contract协定,第二个参数是一个回调ActivityResultCallback<O>,其中O就是Contract的输出类型;返回一个activityResultLauncher对象。 

val activityResultLauncher = registerForActivityResult(MyActivityResultContract()) { result ->

    Toast.makeText(this, "result value is :$result", Toast.LENGTH_LONG).show() 

}

注册了MyActivityResultContract,registerForActivityResult方法的返回值是ActivityResultLauncher。回调方法中result就是从上一个界面传回的值,这里简略的用Toast显示。

③调用启动器的launch办法开启界面跳转

用返回的launcher对象启动另一个activity界面

btn_start_second.setOnClickListener { 

    activityResultLauncher.launch("second activity start") 

launch方法的参数就是要传递给下一个页面的数据。

④新页面通过setResult(int resultCode, Intent data)回传数据。

SecondActivity中的代码不需要修改,这部分代码并没有被废弃,Activity Result API与它无关。

class SecondActivity: AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_second)

        val input = intent.getStringExtra("input")

        textview.text = "接到的数据为: $input"

        btn_second.setOnClickListener {

            val intent = Intent().apply {

                putExtra("result", "我是从second activity回传回来的数据")

            }

            setResult(RESULT_OK, intent)

            finish()

        }

    }

}

这样就完成了用Activity Result API实现Activity之间的数据传递,并获取到Activity返回的结果。

使用Activity Result API完全移除了对onActivityResult()方法的重写,而是通过调用registerForActivityResult()方法注册了一个对Activity结果的监听。

 

3.内置的Contract

使用Activity Result API每次都得定义Contract,因此Google内置了很多Contract,它们都定义在类ActivityResultContracts中:

①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中,应用最多的就是StartActivityForResult和RequestMultiplePermissions了。

有了这些内置的Contract,Activity之间传递数据就简单多了。

1)比如上面的例子,能够简化成这样:

①注册协定,获取ActivityResultLauncher:

 private val myActivityLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){ activityResult ->  

    if(activityResult.resultCode == Activity.RESULT_OK){

        val result = activityResult.data?.getStringExtra("result")

        Toast.makeText(applicationContext, result, Toast.LENGTH_SHORT).show()

        textView.text = "回传数据:$result"

    }

}

②启动页面跳转

 button.setOnClickListener {

    val intent = Intent(this, SecondActivity::class.java).apply {

         putExtra("input","Hello,技术最TOP")

    }

    myActivityLauncher.launch(intent)

}

2)再比如,权限申请:

request_permission.setOnClickListener {

    requestPermission.launch( permission.BLUETOOTH)

}

request_multiple_permission.setOnClickListener {

    requestMultiplePermissions.launch(

        arrayOf(

            permission.BLUETOOTH,

            permission.NFC,

            permission.ACCESS_FINE_LOCATION

        )

    )

}

// 申请单个权限

private val requestPermission = registerForActivityResult( ActivityResultContracts.RequestPermission()) { isGranted ->

        if (isGranted) toast("Permission is granted")

        else toast("Permission is denied")

    }

// 申请一组权限

private val requestMultiplePermissions = registerForActivityResult( ActivityResultContracts.RequestMultiplePermissions()) { permissions : Map<String, Boolean> ->

        permissions.entries.forEach {

            // Do checking here

        }                                                                     

}

由于是请求运行时权限,因此不能再使用刚才的StartActivityForResult来作为Contract了,而是要使用RequestPermission这种Contract。

由于指定了不同的Contract,Lambda表达式的参数也会发生变化。现在Lambda表达式会传入一个布尔型的参数,用于告诉用户是否允许了请求的权限。

最后,launch()方法的参数也发生了变化,现在只需传入要请求的权限名即可。

有了这个就能够摒弃所有的第三方权限申请框架,只需要将这两个Contract放到BaseActivity中,或者抽取到一个独自的类中,就能随时随地申请权限。

这两段代码的模板很相似,使用两段差不多的代码就实现了之前几乎并没有太大联系的两个功能。这就是Activity Result API的好处,它将一些API的接口统一化,使得在实现特定功能的时候能够变得非常简单。

 

4.Activity Result API原理

1)Activity Result API由Launcher、Contract、Callback三个要素组成。

@Override

public final <I, O> ActivityResultLauncher<I> registerForActivityResult(ActivityResultContract<I, O> contract, ActivityResultCallback<O> callback) {

    return registerForActivityResult(contract, mActivityResultRegistry, callback);

}

①ActivityResultLauncher

public abstract class ActivityResultLauncher<I> {

    public void launch(I input) {

        launch(input, null);

    }

    public abstract void launch(I input, ActivityOptionsCompat options);

    @MainThread

    public abstract void unregister();

    public abstract ActivityResultContract<I, ?> getContract();

}

ActivityResultLauncher是registerForActivityResult的返回值,用于连接启动对象和返回对象。

②ActivityResultContract

ActivityResultContract是registerForActivityResult的第一个入参,约定了一个输入类型和一个结果的返回类型。

public abstract class ActivityResultContract<I, O> {

    public abstract Intent createIntent(Context context, I input);

    public abstract O parseResult(int resultCode, Intent intent);

    public SynchronousResult<O> getSynchronousResult(Context context, I input){

        return null;

    }

    public static final class SynchronousResult<T> {

        private final T mValue;

        public SynchronousResult(T value) {

            this.mValue = value;

        }

        public T getValue() {

            return mValue;

        }

    }

}

ActivityResultContract里主要有两个方法,createIntent()方法创建一个Intent用于startActivityForResult;parseResult()方法用于对onActivityResult的结果进行转换。

ActivityResultContracts里提供了常用的ActivityResultContract,可以直接拿来使用。

比如最常用的跳转新页面回传数据StartActivityForResult:

public static final class StartActivityForResult extends ActivityResultContract<Intent, ActivityResult> {

    public static final String EXTRA_ACTIVITY_OPTIONS_BUNDLE = "androidx.activity.result" + ".contract.extra.ACTIVITY_OPTIONS_BUNDLE";

    @Override

    public Intent createIntent(Context context, Intent input) {

        return input;

    }

    @Override

    public ActivityResult parseResult(int resultCode, Intent intent) {

        return new ActivityResult(resultCode, intent);

    }

}

继承ActivityResultContract,约定输入类型为Intent,结果返回类型为ActivityResult。在createIntent方法中因为输入类型就是Intent,所以没做处理,直接返回。parseResult方法中根据指定的resultCode和intent,创建了一个ActivityResult实例返回。

再看一个ActivityResultContracts.TakePicturePreview:

public static class TakePicturePreview extends ActivityResultContract<Void, Bitmap> {

    @Override

    public Intent createIntent(Context context, Void input) {

        return new Intent( MediaStore.ACTION_IMAGE_CAPTURE);

    }

    @Override

    public final SynchronousResult<Bitmap> getSynchronousResult(Context context,Void input) {

        return null;

    }

    @Override

    public final Bitmap parseResult(int resultCode, Intent intent) {

        if (intent == null || resultCode != Activity.RESULT_OK) return null;

        return intent.getParcelableExtra("data");

    }

}

输入类型为Void,因为在createIntent中自己创建了一个MediaStore.ACTION_IMAGE_CAPTURE的Intent实例。parseResult中根据指定的intent中获取到Bitmap实例返回。

如果ActivityResultContracts里常用的这些无法满足需求,也可以自定义,实现相应的createIntent方法和parseResult方法即可。

③ActivityResultCallback 结果回调

public interface ActivityResultCallback<O> {

    void onActivityResult(O result);

}

2)registerForActivityResult在Activity中的实现

在Activity、Fragment中可以直接使用registerForActivityResult()是因为ComponentActivity和Fragment都实现了ActivityResultCaller接口。

@Override

public final <I, O> ActivityResultLauncher<I> registerForActivityResult(final ActivityResultContract<I, O> contract, final ActivityResultRegistry registry, final ActivityResultCallback<O> callback) {

    return registry.register("activity_rq#" + mNextLocalRequestCode.getAndIncrement(), this, contract, callback);

}

第一个参数使用"activity_rq#" + mNextLocalRequestCode.getAndIncrement()构造了一个key,mNextLocalRequestCode是一个AtomicInteger值,使用这种方式就不需要额外定义REQUEST_CODE来进行区分了。

继续ActivityResultRegistry的register方法:

public final <I, O> ActivityResultLauncher<I> register(final String key, final LifecycleOwner lifecycleOwner, final ActivityResultContract<I, O> contract, final ActivityResultCallback<O> callback) {

    //获取到当前生命周期组件的lifecycle

    Lifecycle lifecycle = lifecycleOwner.getLifecycle();

    //register要在当前生命周期组件处于STARTED状态之前调用

    if (lifecycle.getCurrentState().isAtLeast( Lifecycle.State.STARTED)) {

        throw new IllegalStateException( "LifecycleOwner " + lifecycleOwner + " is attempting to register while current state is " + lifecycle.getCurrentState() + ". LifecycleOwners must call register before they are STARTED.");

    }

    //通过传入的key生成requestCode

    final int requestCode = registerKey(key);

    //通过key在集合中获取LifecycleContainer实例,没有则生成一个

    LifecycleContainer lifecycleContainer = mKeyToLifecycleContainers.get(key);

    if (lifecycleContainer == null) {

        lifecycleContainer = new LifecycleContainer(lifecycle);

    }

    //生成观察者,当状态为ON_START时执行回调,为ON_STOP时移除与回调的关联,为ON_DESTROY时取消注册

    LifecycleEventObserver observer = new LifecycleEventObserver() {

        @Override

        public void onStateChanged( LifecycleOwner lifecycleOwner, Lifecycle.Event event) {

            if (Lifecycle.Event.ON_START.equals( event)) {

                mKeyToCallback.put(key, new CallbackAndContract<>(callback, contract));

                if (mParsedPendingResults.contai nsKey(key)) {

                    final O parsedPendingResult = (O) mParsedPendingResults.get(key);

                    mParsedPendingResults.remove( key);

                    callback.onActivityResult( parsedPendingResult);

                }

                final ActivityResult pendingResult = mPendingResults.getParcelable(key);

                if (pendingResult != null) {

                    mPendingResults.remove(key);

                    callback.onActivityResult( contract.parseResult(pendingResult.getResultCode(), pendingResult.getData()));

                }

            } else if (Lifecycle.Event.ON_STOP.equ als(event)) {

                mKeyToCallback.remove(key);

            } else if (Lifecycle.Event.ON_DESTRO Y.equals(event)) {

                unregister(key);

            }

        }

    };

    //为LifecycleContainer实例添加观察者

    lifecycleContainer.addObserver(observer);

    mKeyToLifecycleContainers.put(key, lifecycleContainer);

    //返回了一个ActivityResultLauncher实例

    return new ActivityResultLauncher<I>() {

        @Override

        public void launch(I input, ActivityOptionsCompat options) {

            mLaunchedKeys.add(key);

            Integer innerCode = mKeyToRc.get( key);

            onLaunch((innerCode != null) ? innerCode : requestCode, contract, input, options);

        }

        @Override

        public void unregister() {

            ActivityResultRegistry.this.unregister( key);

        }

        @Override

        public ActivityResultContract<I, ?> getContract() {

            return contract;

        }

    };

}

在register方法中,首先获取到当前生命周期组件的lifecycle。然后register要在当前生命周期组件处于STARTED状态之前调用。通过传入的key生成requestCode。通过key在集合中获取LifecycleContainer实例,没有则生成一个。生成观察者,当状态为ON_START时执行回调,为ON_STOP时移除与回调的关联,为ON_DESTROY时取消注册。为LifecycleContainer实例添加观察者。最终返回了一个ActivityResultLauncher实例。

3)onLaunch在Activity中的实现

在registerForActivityResult中最终返回了ActivityResultLauncher实例,而ActivityResultLauncher的launch方法里调用了ActivityResultRegistry.onLaunch方法,该方法是一个抽象方法,其实现在ComponentActivity中。

this.mActivityResultRegistry = new ActivityResultRegistry() {

    public <I, O> void onLaunch(final int requestCode, ActivityResultContract<I, O> contract, I input, ActivityOptionsCompat options) {

        ComponentActivity activity = ComponentActivity.this;

        final SynchronousResult<O> synchronousResult = contract.getSynchronousResult(activity, input);

        if (synchronousResult != null) {

           //不需要启动Activity就能知道结果的场景处理

            (new Handler(Looper.getMainLooper()) ).post(new Runnable() {

                public void run() {

                    dispatchResult(requestCode, synchronousResult.getValue());

                }

            });

        } else {  //需要启动Activity才能知道结果的场景处理

            //通过ActivityResultContract.createIntent初始化Intent实例

            Intent intent = contract.createIntent( activity, input);

            //初始化Bundle

            Bundle optionsBundle = null;

            if (intent.getExtras() != null && intent.getExtras().getClassLoader() == null) {

                intent.setExtrasClassLoader( activity.getClassLoader());

            }

            if (intent.hasExtra("androidx.activity.res ult.contract.extra.ACTIVITY_OPTIONS_BUNDLE")) {

                optionsBundle = intent.getBundleExtra("androidx.activity.result.contract.extra.ACTIVITY_OPTIONS_BUNDLE");

                intent.removeExtra( "androidx.activity.result.contract.extra.ACTIVITY_OPTIONS_BUNDLE");

            } else if (options != null) {

                optionsBundle = options.toBundle();

            }

            //如果是权限申请,请求权限

            if ("androidx.activity.result.contract.ac tion.REQUEST_PERMISSIONS".equals(intent.getAction())) {

                String[] permissions = intent.getStringArrayExtra("androidx.activity.result.contract.extra.PERMISSIONS");

                if (permissions == null) {

                    permissions = new String[0];

                }

                ActivityCompat.requestPermissions( activity, permissions, requestCode);

            } else if ("androidx.activity.result.contr act.action.INTENT_SENDER_REQUEST".equals(intent.getAction())) {

                IntentSenderRequest request = (IntentSenderRequest)intent.getParcelableExtra("androidx.activity.result.contract.extra.INTENT_SENDER_REQUEST");

                try {

                    ActivityCompat.startIntentSende rForResult(activity, request.getIntentSender(), requestCode, request.getFillInIntent(), request.getFlagsMask(), request.getFlagsValues(), 0, optionsBundle);

                } catch (final SendIntentException var11) {

                    (new Handler(Looper.getMainLoo per())).post(new Runnable() {

                        public void run() {

                            dispatchResult( requestCode, 0, (new Intent()).setAction("androidx.act ivity.result.contract.action.INTENT_SENDER_REQUEST").putExtra("androidx.activity.result.contract.extra.SEND_INTENT_EXCEPTION", var11));

                        }

                    });

                }

            } else {

                ActivityCompat.startActivityForRes ult(activity, intent, requestCode, optionsBundle);

            }

        }

    }

};

首先区分是否需要启动Activity,需要启动Activity的情况下通过ActivityResultContract.createIntent初始化Intent实例,初始化Bundle,最终也是通过ActivityCompat.startActivityForResult跳转新页面。

总结:

①ComponentActivity内部初始化了一个ActivityResultRegistry实例,并重写了 onLaunch()。

②调用registerForActivityResult() 最终调用ActivityResultRegistry.register(),在此添加了一个观察者,当生命周期状态切换到ON_START时,执行Contract.parseResult()生成输出内容,并把结果作为参数传入回调callback.onActivityResult()中。

③调用ActivityResultLauncher.launch()才会发起跳转,其中回调了onLaunch()方法,在此调用了Contract.createIntent()创建一个和startActivityForResult()搭配使用的Intent实例。

④跳转目标Activity后返回此页面,生命周期发生改变,在观察者中就会执行回调的相关代码。

 

注意:

当一个页面上需要一下子通过同一个ActivityResultLauncher打开多个页面时,发现在不同Android版本上表现不一样。

每一个registerForActivityResult内部会生成一个RequestCode作为key,ActivityResultLauncher有一个观察者队列,ON_START会添加观察者,ON_STOP会移除观察者。

当onActivityResult回调时,执行dispatchResult方法,从观察者队列中取出观察者进行回传,进行doDispatch方法。

关键在doDispatch方法中,有观察者进行观察者的onActivityResult回调,没有观察者,使用key将数据存储在bundle信息中。

protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    if (!mActivityResultRegistry.dispatchResult( requestCode, resultCode, data)) {

        super.onActivityResult(requestCode, resultCode, data);

    }

}

@MainThread

public final boolean dispatchResult(int requestCode, int resultCode, Intent data) {

    String key = mRcToKey.get(requestCode);

    if (key == null) {

        return false;

    }

    doDispatch(key, resultCode, data, mKeyToCallback.get(key));

    return true;

}

private <O> void doDispatch(String key, int resultCode, Intent data, CallbackAndContract<O> callbackAndContract) {

    if (callbackAndContract != null && callbackAndContract.mCallback != null && mLaunchedKeys.contains(key)) {

        ActivityResultCallback<O> callback = callbackAndContract.mCallback;

        ActivityResultContract<?, O> contract = callbackAndContract.mContract;

        callback.onActivityResult( contract.parseResult(resultCode, data));

        mLaunchedKeys.remove(key);

    } else {

        mParsedPendingResults.remove(key);

        mPendingResults.putParcelable(key, new ActivityResult(resultCode, data));

    }

}

在Android13系统上,回到页面时先ON_START会添加观察者,再onActivityResult回调,没有问题。

而在Android10系统上,回到页面时先onActivityResult回调,由于观察者还未添加回队列,所以使用key存储bundle信息的,因此多次使用同一个registerForActivityResult时会丢失数据,使用key存储bundle信息会覆盖,只留下最后一次返回的bundle信息。

 

到了这里,关于Android Activity Result API的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • [Android 四大组件] --- Activity

    ​​Activity​​是一个Android的应用组件,它提供屏幕进行交互。每个Activity都会获得一个用于绘制其用户界面的窗口,窗口可以充满哦屏幕也可以小于屏幕并浮动在其他窗口之上。 一个应用通常是由多个彼此松散联系的Activity组成,一般会指定应用中的某个Activity为主活动,也

    2024年02月10日
    浏览(45)
  • Android Studio系列-Activity单元测试,字节Android高级岗

    新建Activity单元测试类 =============== package com.devilwwj.unittestdemo; import android.content.Intent; import android.test.ActivityUnitTestCase; import android.test.suitebuilder.annotation.MediumTest; import android.widget.Button; /** Created by wwj_748 on 2016/2/22.17.12 */ public class LoginActivityTest extends ActivityUnitTestCase { private Inten

    2024年04月25日
    浏览(61)
  • Android复习(Android基础-四大组件)——Service与Activity通信

    我们前面学会了启动和停止服务的方法,但是服务虽然是在活动里启动的,但是启动服务之后,活动与服务之间基本没什么关系了。 正常情况,我们在Activity里调用startService()方法启动MyService这个服务,然后MyService的onCreate()和onStartCommand()方法就会得到执行。之后服务会一直处

    2024年02月13日
    浏览(44)
  • Android Activity 动画如何实现

    在 Android 中,你可以使用 Activity 转场动画来实现 Activity 之间的切换动画效果。以下是一些常见的 Activity 转场动画的实现方法: 1. 使用 XML 文件定义动画效果: 首先,在 res/anim 目录下创建 XML 文件来定义你的动画效果。例如,你可以创建 fade_in.xml 和 fade_out.xml 文件来定义淡入

    2024年02月09日
    浏览(49)
  • Android内嵌Unity (Activity)

    Unity2019.4.4 AndropidStudio4.2.1 参考文档: Android内嵌Unity并实现互相跳转的实例代码_Android_脚本之家 Android Fragment中加载,嵌套Unity视图_unity 导入并作为fragment_周灬浩的博客-CSDN博客 本文只实现了Activity整个切换过去,而Fragment,这种像h5似的与app共存,目前还未实现,可参考的第二

    2024年01月18日
    浏览(42)
  • Android Activity启动过程详解

    1,《android系统启动流程简介》 2,《android init进程启动流程》 3,《android zygote进程启动流程》 4,《Android SystemServer进程启动流程》 5,《android launcher启动流程》 6,《Android Activity启动过程详解》 1,《Android 源码下载和编译》 2,《android 11源码编译和pixel3 刷机》 3,《Andro

    2024年02月09日
    浏览(52)
  • Android 后台启动Activity适配

    在Android 9及以下版本,后台启动Activity相对自由,但是如果在Activity上下文之外启动Activity会有限制。 所以此时需要给intent添加flag:FLAG_ACTIVITY_NEW_TASK。 在Android版本10及以后版本, 引入了后台执行限制,限制了应用在后台执行操作的能力。非核心任务的后台启动 Activity 可能会

    2024年02月10日
    浏览(45)
  • Android Activity启动流程一:从Intent到Activity创建

    关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。 学习前,建议有相关知识储备: 【Android 基础】 应用(Application)启动流程 通过本文你可以学习到Activity启动流

    2024年02月10日
    浏览(47)
  • Android 四大组件之Activity详解

      最近在整理Android方面的知识,也算是对Android知识的一个复习总结。   Activity是Android组件中最基本也是最为常见用的四大组件之一,它提供一个可视化的用户界面,放置各种UI组件,与用户进行交互。一般来说,你所能看到界面都属于Activity。 右击包名——New——Acti

    2024年04月15日
    浏览(74)
  • Android开发笔记(三)—Activity篇

    (1)从当前页面跳到新页面: startActivity(new Intent(源页面.this,目标页面.class)) (2)从当前页面回到上一个页面,相当于关闭当前页面: finish() onCreate:创建活动。把页面布局加载到内存,进入了初始状态。 onStart:开始活动。把活动页面显示在屏幕上,进入了就绪状态。 on

    2024年02月06日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包