国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Flutter 和 Android原生(Activity、Fragment)相互跳轉(zhuǎn)、傳參

這篇具有很好參考價值的文章主要介紹了Flutter 和 Android原生(Activity、Fragment)相互跳轉(zhuǎn)、傳參。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

前言

本文主要講解 Flutter 和 Android原生之間,頁面相互跳轉(zhuǎn)、傳參,

但其中用到了兩端相互通信的知識,非常建議先看完這篇 講解通信的文章

Flutter 與 Android原生 相互通信:BasicMessageChannel、MethodChannel、EventChannel_flutter eventchannel methodchannel basemessagechan-CSDN博客

當前案例 Flutter SDK版本:3.13.2

Flutter使用多個輕量型引擎,進行混合開發(fā),是從?2.0?開始的,大大的減輕了內(nèi)存壓力;

輕量型引擎開發(fā)-官方介紹視頻:https://www.youtube.com/watch?v=p6cK_0jp2ag

Flutter和原生端的關(guān)系

Flutter 和 Android原生(Activity、Fragment)相互跳轉(zhuǎn)、傳參,Flutter + Android 混合開發(fā),flutter,androidFlutter 和 Android原生(Activity、Fragment)相互跳轉(zhuǎn)、傳參,Flutter + Android 混合開發(fā),flutter,android

混合路由棧

如果是純Flutter開發(fā),只會有一個Flutter引擎,如果是混合開發(fā),原生端 需要為每個從原生端跳轉(zhuǎn)的Flutter頁面創(chuàng)建獨立的引擎?(也可以單例,但單例寫法需要處理一些問題,這個到?FlutterEngineGroup 章節(jié)會具體講解);

比如:

1.0?從 Android_A頁面? ==== 跳轉(zhuǎn)到 ==== Flutter_A頁面,Android端需要為Flutter_A頁面,創(chuàng)建Flutter引擎;

1.1 緊接著,從 Flutter_A頁面?==== 跳轉(zhuǎn)到 ==== Flutter_B頁面,就不需要,它倆共用一個引擎;

1.2?每個Flutter引擎都有自己的路由棧,且這個路由棧只能管理Flutter頁面;

1.3 使用Flutter提供的?Navigator.pop(context);?方法,可以從 Flutter_B頁面 回退到 Flutter_A頁面,但無法從 Flutter_A頁面 回退到 Android_A,會黑屏,因為Flutter棧里面沒有Android頁面,可以使用?Navigator.canPop(context);?來檢查Flutter路由棧中,是否還有其他路由;

1.4 如果不使用?Navigator.pop(context);?回退方法,使用手機自帶的 Back按鍵 / 左滑屏幕 進行回退,是沒有問題的,因為這種回退方式調(diào)用的是原生API,Android原生不光提供FlutterView渲染Flutter頁面結(jié)果,還會創(chuàng)建FlutterActivityFlutterView進行綁定;

1.5 看到這,大家應(yīng)該理解,為什么說Flutter只是UI框架了吧;

Flutter 和 Android原生(Activity、Fragment)相互跳轉(zhuǎn)、傳參,Flutter + Android 混合開發(fā),flutter,android

Android 和 Flutter 跳轉(zhuǎn)

Android 跳轉(zhuǎn) Flutter

Flutter 和 Android原生(Activity、Fragment)相互跳轉(zhuǎn)、傳參,Flutter + Android 混合開發(fā),flutter,android

Flutter 跳轉(zhuǎn) Android

Flutter 和 Android原生(Activity、Fragment)相互跳轉(zhuǎn)、傳參,Flutter + Android 混合開發(fā),flutter,android

效果圖

Flutter 和 Android原生(Activity、Fragment)相互跳轉(zhuǎn)、傳參,Flutter + Android 混合開發(fā),flutter,android

Android代碼

FlutterRouterManager.kt

package com.example.flutter_nav_android.util

import android.app.Activity
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.android.FlutterActivityLaunchConfigs
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.engine.FlutterEngineCache
import io.flutter.embedding.engine.dart.DartExecutor

class FlutterRouterManager(
    val targetRoute: String,
    val mEngineId: String,
    val mContext: Activity
) {

    var mEngine: FlutterEngine? = null

    init {
        createCachedEngine()
    }

    companion object {

        /**
         * 獲取緩存中的 Flutter引擎
         */
        @JvmStatic
        fun getEngineCacheInstance(engineId: String): FlutterEngine? {
            return FlutterEngineCache.getInstance().get(engineId)
        }

    }

    /**
     * 1、創(chuàng)建Flutter引擎
     * 2、將初始命名路由,修改為目標頁面路由
     * 3、緩存Flutter引擎
     */
    fun createCachedEngine(): FlutterEngine {
        val flutterEngine = FlutterEngine(mContext) // 創(chuàng)建Flutter引擎

        // 將初始命名路由,修改為目標頁面路由
        flutterEngine.navigationChannel.setInitialRoute(targetRoute)

        // 這一步,是在執(zhí)行相關(guān)Dart文件入口的 main函數(shù),將Flutter頁面渲染出結(jié)果
        // 原生端獲取結(jié)果,進行最終渲染上屏
        flutterEngine.dartExecutor.executeDartEntrypoint(
            DartExecutor.DartEntrypoint.createDefault()
        )

        // 將加載好的引擎,存儲起來
        FlutterEngineCache.getInstance().put(mEngineId, flutterEngine)

        mEngine = flutterEngine

        return flutterEngine
    }

    /**
     * 根據(jù)引擎ID,前往指定的Flutter頁面
     */
    fun push() {
        // 創(chuàng)建新的引擎(了解即可)
        // mContext.startActivity(
        //    FlutterActivity
        //        .withNewEngine() // 創(chuàng)建引擎
        //        .backgroundMode(FlutterActivityLaunchConfigs.BackgroundMode.transparent) // 背景改為透明,不然切換頁面時,會閃爍黑色
        //        .build(mContext))

        // 使用緩存好的引擎(推薦)
        mContext.startActivity(
            FlutterActivity
                .withCachedEngine(mEngineId) // 獲取緩存好的引擎
                .backgroundMode(FlutterActivityLaunchConfigs.BackgroundMode.transparent) // 背景改為透明,不然切換頁面時,會閃爍黑色
                .build(mContext)
        )
    }

    /**
     * 銷毀當前Flutter引擎
     */
    fun destroy() {
        mEngine?.destroy()
    }

}

PersonalActivity.kt

package com.example.flutter_nav_android.ui.activity

import android.graphics.Color
import android.os.Bundle
import android.text.SpannableString
import android.text.Spanned
import android.text.style.ForegroundColorSpan
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import com.example.flutter_nav_android.databinding.ActivityPersonalBinding
import com.example.flutter_nav_android.util.FlutterRouterManager
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel

class PersonalActivity : AppCompatActivity(), MethodChannel.MethodCallHandler, View.OnClickListener {

    private lateinit var bind: ActivityPersonalBinding

    private lateinit var homeFlutterEngine: FlutterEngine
    private lateinit var loginRouterManager: FlutterRouterManager

    private lateinit var loginMethodChannel: MethodChannel
    private lateinit var homeMethodChannel: MethodChannel

    private val METHOD_CHANNEL_LOGIN = "com.example.flutter_nav_android/login/method"
    private val METHOD_CHANNEL_HOME = "com.example.flutter_nav_android/home/method"
    private val NAV_FLUTTER_LOGIN_NOTICE = "navFlutterLoginNotice"
    private val POP_NOTICE = "popNotice"
    private val PERSONAL_POP_NOTICE = "personalPopNotice"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        bind = ActivityPersonalBinding.inflate(layoutInflater)
        setContentView(bind.root)
        initView()

        loginRouterManager = FlutterRouterManager("/login", "login_engine", this)

        // 兩端建立通信
        loginMethodChannel = MethodChannel(loginRouterManager.mEngine!!.dartExecutor, METHOD_CHANNEL_LOGIN)
        loginMethodChannel.setMethodCallHandler(this)

        // 獲取 Flutter Home頁面的引擎,并且建立通信
        homeFlutterEngine = FlutterRouterManager.getEngineCacheInstance("home_engine")!!
        homeMethodChannel = MethodChannel(homeFlutterEngine.dartExecutor,METHOD_CHANNEL_HOME)
    }

    /**
     * 監(jiān)聽來自 Flutter端 的消息通道
     *
     * call: Android端 接收到 Flutter端 發(fā)來的 數(shù)據(jù)對象
     * result:Android端 給 Flutter端 執(zhí)行回調(diào)的接口對象
     */
    override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
        val methodName: String = call.method
        when (methodName) { // 銷毀 Flutter Login 頁面
            POP_NOTICE -> {
                val age = call.argument<Int>("age")
                getResult(age.toString())
                loginRouterManager.mEngine!!.navigationChannel.popRoute()
            }
            else -> {
                result.notImplemented()
            }
        }
    }

    override fun onClick(v: View?) {
        when (v) {
            bind.toFlutter -> { // 前往 Flutter Login 頁面
                val map: MutableMap<String, String> = mutableMapOf<String, String>()
                map["name"] = "老王"
                loginMethodChannel.invokeMethod(NAV_FLUTTER_LOGIN_NOTICE,map)
                loginRouterManager.push()
            }
            bind.pop -> { // 銷毀 Android Personal 頁面
                val map: MutableMap<String, Int> = mutableMapOf<String, Int>()
                map["age"] = 18
                homeMethodChannel.invokeMethod(PERSONAL_POP_NOTICE,map)
                finish()
            }
        }
    }

    /**
     * 初始化頁面
     */
    private fun initView() {
        bind.toFlutter.setOnClickListener(this)
        bind.pop.setOnClickListener(this)

        var name = intent.getStringExtra("name")
        val title = "接收初始化參數(shù):"
        val msg = title + name

        val ss = SpannableString(msg)
        ss.setSpan(
            ForegroundColorSpan(Color.RED),
            title.length,
            msg.length,
            Spanned.SPAN_INCLUSIVE_EXCLUSIVE
        )
        bind.initV.text = ss
    }

    /**
     * 獲取上一頁的返回參數(shù)
     */
    private fun getResult(age: String) {
        val title = "接收上一頁返回參數(shù):"
        val msg = title + age

        val ss = SpannableString(msg)
        ss.setSpan(
            ForegroundColorSpan(Color.RED),
            title.length,
            msg.length,
            Spanned.SPAN_INCLUSIVE_EXCLUSIVE
        )
        bind.resultV.text = ss
    }

    override fun onDestroy() {
        super.onDestroy()
        loginRouterManager.destroy()
    }

}

SchoolActivity.kt

package com.example.flutter_nav_android.ui.activity

import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.example.flutter_nav_android.databinding.ActivitySchoolBinding
import com.example.flutter_nav_android.util.FlutterRouterManager
import io.flutter.embedding.android.FlutterFragment
import io.flutter.embedding.android.TransparencyMode
import io.flutter.embedding.engine.FlutterEngineCache
import io.flutter.plugin.common.MethodChannel


class SchoolActivity : AppCompatActivity() {

    private lateinit var bind: ActivitySchoolBinding
    private lateinit var bookFragment: FlutterFragment
    private lateinit var studentFragment: FlutterFragment

    private val METHOD_CHANNEL_BOOK = "com.example.flutter_nav_android/book/method"
    private val METHOD_CHANNEL_STUDENT = "com.example.flutter_nav_android/student/method"

    private val NAV_FLUTTER_BOOK_NOTICE = "navFlutterBookNotice"
    private val NAV_FLUTTER_STUDENT_NOTICE = "navFlutterStudentNotice"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        bind = ActivitySchoolBinding.inflate(layoutInflater)
        setContentView(bind.root)
        initView()
        initChannel()
    }

    /**
     * 建立通信
     */
    private fun initChannel() {
        val bookEngine = FlutterRouterManager.getEngineCacheInstance("book_engine")
        val bookChannel = MethodChannel(bookEngine!!.dartExecutor,METHOD_CHANNEL_BOOK)
        val map: MutableMap<String, String> = mutableMapOf<String, String>()
        map["title"] = "Book"
        bookChannel.invokeMethod(NAV_FLUTTER_BOOK_NOTICE,map)

        val studentEngine = FlutterRouterManager.getEngineCacheInstance("student_engine")
        val studentChannel = MethodChannel(studentEngine!!.dartExecutor,METHOD_CHANNEL_STUDENT)
        val map2: MutableMap<String, String> = mutableMapOf<String, String>()
        map2["title"] = "Student"
        studentChannel.invokeMethod(NAV_FLUTTER_STUDENT_NOTICE,map2)
    }

    /**
     * 初始化頁面
     */
    private fun initView() {
        bookFragment = FlutterFragment.withCachedEngine("book_engine")
            .transparencyMode(TransparencyMode.transparent) // 背景透明,避免切換頁面,出現(xiàn)閃爍
            .shouldAttachEngineToActivity(false) // 是否讓Flutter控制Activity,true:可以 false:不可以,默認值 true
            .build()

        supportFragmentManager
            .beginTransaction()
            .add(bind.bookFragment.id, bookFragment)
            .commit()

        studentFragment = FlutterFragment.withCachedEngine("student_engine")
            .transparencyMode(TransparencyMode.transparent) // 背景透明,避免切換頁面,出現(xiàn)閃爍
            .shouldAttachEngineToActivity(false) // 是否讓Flutter控制Activity,true:可以 false:不可以,默認值 true
            .build()

        supportFragmentManager
            .beginTransaction()
            .add(bind.studentFragment.id, studentFragment)
            .commit()
    }

    // ================================ 這些是固定寫法,F(xiàn)lutter需要這些回調(diào) ================================

    override fun onPostResume() {
        super.onPostResume()
        bookFragment.onPostResume()
        studentFragment.onPostResume()
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        bookFragment.onNewIntent(intent)
        studentFragment.onNewIntent(intent)
    }

    override fun onBackPressed() {
        bookFragment.onBackPressed()
        studentFragment.onBackPressed()
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<String?>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        bookFragment.onRequestPermissionsResult(
            requestCode,
            permissions,
            grantResults
        )
        studentFragment.onRequestPermissionsResult(
            requestCode,
            permissions,
            grantResults
        )
    }

    override fun onUserLeaveHint() {
        bookFragment.onUserLeaveHint()
        studentFragment.onUserLeaveHint()
    }

    override fun onTrimMemory(level: Int) {
        super.onTrimMemory(level)
        bookFragment.onTrimMemory(level)
        studentFragment.onTrimMemory(level)
    }

}

MainActivity.kt

package com.example.flutter_nav_android.ui.activity

import android.content.Intent
import android.graphics.Color
import android.text.SpannableString
import android.text.Spanned
import android.text.style.ForegroundColorSpan
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import com.example.flutter_nav_android.databinding.ActivityMainBinding
import com.example.flutter_nav_android.util.FlutterRouterManager
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel


class MainActivity : AppCompatActivity(), MethodChannel.MethodCallHandler, View.OnClickListener {

    private lateinit var bind: ActivityMainBinding

    private lateinit var homeMethodChannel: MethodChannel

    private val METHOD_CHANNEL_HOME = "com.example.flutter_nav_android/home/method"
    private val NAV_ANDROID_PERSONAL_NOTICE = "navAndroidPersonalNotice"
    private val NAV_FLUTTER_HOME_NOTICE = "navFlutterHomeNotice"
    private val POP_NOTICE = "popNotice"

    private lateinit var homeRouterManager: FlutterRouterManager
    private lateinit var bookRouterManager: FlutterRouterManager
    private lateinit var studentRouterManager: FlutterRouterManager

    override fun onCreate(savedInstanceState: android.os.Bundle?) {
        super.onCreate(savedInstanceState)
        bind = ActivityMainBinding.inflate(layoutInflater)
        setContentView(bind.root)
        bind.toFlutter.setOnClickListener(this)
        bind.toFlutterFragment.setOnClickListener(this)

        homeRouterManager = FlutterRouterManager("/home", "home_engine", this)

        // 兩端建立通信
        homeMethodChannel = MethodChannel(homeRouterManager.mEngine!!.dartExecutor,METHOD_CHANNEL_HOME)
        homeMethodChannel.setMethodCallHandler(this)

        // 這里Fragment案例的
        bookRouterManager = FlutterRouterManager("/book", "book_engine", this)
        studentRouterManager = FlutterRouterManager("/student", "student_engine", this)
    }

    /**
     * 監(jiān)聽來自 Flutter端 的消息通道
     *
     * call: Android端 接收到 Flutter端 發(fā)來的 數(shù)據(jù)對象
     * result:Android端 給 Flutter端 執(zhí)行回調(diào)的接口對象
     */
    override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
        val methodName: String = call.method
        when (methodName) {
            NAV_ANDROID_PERSONAL_NOTICE -> { // Flutter Home 頁面 前往 Android Personal 頁面
                val intent = Intent(this, PersonalActivity::class.java)
                intent.putExtra("name",call.argument<String>("name"))
                startActivity(intent)
            }
            POP_NOTICE -> { // 銷毀 Flutter Home 頁面
                val age = call.argument<Int>("age")
                getResult(age.toString())
                homeRouterManager.mEngine!!.navigationChannel.popRoute()
            }
            else -> {
                result.notImplemented()
            }
        }
    }

    override fun onClick(v: View?) {
        when (v) {
            bind.toFlutter -> { // 前往 Flutter Home 頁面
                val map: MutableMap<String, String> = mutableMapOf<String, String>()
                map["name"] = "張三"
                homeMethodChannel.invokeMethod(NAV_FLUTTER_HOME_NOTICE,map)
                homeRouterManager.push()
            }
            bind.toFlutterFragment -> {
                val intent = Intent(this, SchoolActivity::class.java)
                startActivity(intent)
            }
        }
    }

    /**
     * 獲取上一頁的返回參數(shù)
     */
    private fun getResult(age: String) {
        val title = "接收上一頁返回參數(shù):"
        val msg = title + age

        val ss = SpannableString(msg)
        ss.setSpan(
            ForegroundColorSpan(Color.RED),
            title.length,
            msg.length,
            Spanned.SPAN_INCLUSIVE_EXCLUSIVE
        )
        bind.resultV.text = ss
    }

    override fun onDestroy() {
        super.onDestroy()
        homeRouterManager.destroy()
        bookRouterManager.destroy()
        studentRouterManager.destroy()
    }

}

activity_personal.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/app_bar"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:layout_marginBottom="16dp"
            android:background="@color/cardview_shadow_start_color"
            android:gravity="center_vertical"
            android:paddingStart="16dp"
            android:text="Android Personal"
            android:textColor="@color/material_dynamic_primary60"
            android:textSize="26sp"
            android:textStyle="bold"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/init_v"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center_vertical"
            android:text="接收初始化參數(shù):"
            android:textColor="@color/material_dynamic_primary60"
            android:textSize="20sp"
            android:textStyle="bold"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/result_v"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:text="接收上一頁返回參數(shù):"
            android:textColor="@color/material_dynamic_primary60"
            android:textSize="20sp"
            android:textStyle="bold"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@id/init_v" />

        <Button
            android:id="@+id/to_flutter"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:text="前往 Flutter Login"
            android:textSize="20sp"
            android:textAllCaps="false"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@id/result_v" />

        <Button
            android:id="@+id/pop"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text="返回 上一頁"
            android:textSize="20sp"
            android:textAllCaps="false"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@id/to_flutter" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>

activity_school.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingTop="20dp"
        android:orientation="vertical">

        <TextView
            android:id="@+id/app_bar"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:background="@color/cardview_shadow_start_color"
            android:gravity="center_vertical"
            android:paddingStart="16dp"
            android:text="Android School"
            android:textColor="@color/material_dynamic_primary60"
            android:textSize="26sp"
            android:textStyle="bold" />

        <FrameLayout
            android:id="@+id/book_fragment"
            android:layout_weight="1"
            android:layout_width="match_parent"
            android:layout_height="0dp" />

        <FrameLayout
            android:id="@+id/student_fragment"
            android:layout_weight="1"
            android:layout_width="match_parent"
            android:layout_height="0dp" />

    </LinearLayout>
</layout>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/app_bar"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:layout_marginBottom="16dp"
            android:background="@color/cardview_shadow_start_color"
            android:gravity="center_vertical"
            android:paddingStart="16dp"
            android:text="Android Main"
            android:textColor="@color/material_dynamic_primary60"
            android:textSize="26sp"
            android:textStyle="bold"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/result_v"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center_vertical"
            android:text="接收上一頁返回參數(shù):"
            android:textColor="@color/material_dynamic_primary60"
            android:textSize="20sp"
            android:textStyle="bold"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"/>

        <Button
            android:id="@+id/to_flutter"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:text="前往 Flutter Home"
            android:textSize="20sp"
            android:textAllCaps="false"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toBottomOf="@id/result_v"
            app:layout_constraintRight_toRightOf="parent" />

        <Button
            android:id="@+id/to_flutter_fragment"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:text="前往 Flutter Fragment"
            android:textSize="20sp"
            android:textAllCaps="false"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toBottomOf="@id/to_flutter"
            app:layout_constraintRight_toRightOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android">


    <application
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher"
        android:label="flutter_nav_android"
        android:theme="@style/AppTheme">

        <activity
            android:name="io.flutter.embedding.android.FlutterActivity"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize" />

        <activity android:name=".ui.activity.SchoolActivity" android:exported="true"/>

        <activity android:name=".ui.activity.PersonalActivity" android:exported="true"/>

        <activity
            android:name=".ui.activity.MainActivity"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:exported="true"
            android:hardwareAccelerated="true"
            android:launchMode="singleTop"
            android:windowSoftInputMode="adjustResize">
            <!-- Specifies an Android theme to apply to this Activity as soon as
                 the Android process has started. This theme is visible to the user
                 while the Flutter UI initializes. After that, this theme continues
                 to determine the Window background behind the Flutter UI. -->
            <meta-data
                android:name="io.flutter.embedding.android.NormalTheme"
                android:resource="@style/NormalTheme" />
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
    </application>
    <!-- Required to query activities that can process text, see:
         https://developer.android.com/training/package-visibility?hl=en and
         https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.

         In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
    <queries>
        <intent>
            <action android:name="android.intent.action.PROCESS_TEXT" />
            <data android:mimeType="text/plain" />
        </intent>
    </queries>
</manifest>

Flutter代碼

book.dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class Book extends StatefulWidget {
  const Book({super.key});

  @override
  State<Book> createState() => _BookState();
}

class _BookState extends State<Book> {

  String title = '';

  static const String METHOD_CHANNEL_BOOK = 'com.example.flutter_nav_android/book/method';
  static const String NAV_FLUTTER_BOOK_NOTICE = 'navFlutterBookNotice';

  @override
  void initState() {
    super.initState();
    MethodChannel bookMethodChannel = const MethodChannel(METHOD_CHANNEL_BOOK);
    bookMethodChannel.setMethodCallHandler(methodHandler);
  }

  /// 監(jiān)聽來自 Android端 的消息通道
  /// Android端調(diào)用了函數(shù),這個handler函數(shù)就會被觸發(fā)
  Future<dynamic> methodHandler(MethodCall call) async {
    final String methodName = call.method;
    switch (methodName) {
      case NAV_FLUTTER_BOOK_NOTICE: // 進入當前頁面
        {
          title = call.arguments['title'];
          setState(() {});
          return 0;
        }
      default:
        {
          return PlatformException(
              code: '-1',
              message: '未找到Flutter端具體實現(xiàn)函數(shù)',
              details: '具體描述'); // 返回給Android端
        }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.amberAccent,
      body: Container(
        width: MediaQuery.of(context).size.width,
        height: MediaQuery.of(context).size.height,
        alignment: Alignment.center,
        child: Text(
          'Flutter $title',
          style: const TextStyle(
            fontWeight: FontWeight.bold,
            color: Colors.red,
            fontSize: 20,
          ),
        ),
      ),
    );
  }

}

home.dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class Home extends StatefulWidget {
  const Home({super.key});

  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {
  late MethodChannel homeMethodChannel;

  String name = '';
  String age = '';

  static const String METHOD_CHANNEL_HOME = 'com.example.flutter_nav_android/home/method';
  static const String NAV_ANDROID_PERSONAL_NOTICE = 'navAndroidPersonalNotice';
  static const String NAV_FLUTTER_HOME_NOTICE = 'navFlutterHomeNotice';
  static const String POP_NOTICE = 'popNotice';
  static const String PERSONAL_POP_NOTICE = 'personalPopNotice';

  @override
  void initState() {
    super.initState();
    homeMethodChannel = const MethodChannel(METHOD_CHANNEL_HOME);
    homeMethodChannel.setMethodCallHandler(methodHandler);
  }

  /// 監(jiān)聽來自 Android端 的消息通道
  /// Android端調(diào)用了函數(shù),這個handler函數(shù)就會被觸發(fā)
  Future<dynamic> methodHandler(MethodCall call) async {
    final String methodName = call.method;
    switch (methodName) {
      case NAV_FLUTTER_HOME_NOTICE: // 進入當前頁面
        {
          name = call.arguments['name'];
          setState(() {});
          return 0;
        }
      case PERSONAL_POP_NOTICE: // Android Personal 頁面 銷毀了
        {
          age = '${call.arguments['age']}';
          setState(() {});
          return 0;
        }
      default:
        {
          return PlatformException(
              code: '-1',
              message: '未找到Flutter端具體實現(xiàn)函數(shù)',
              details: '具體描述'); // 返回給Android端
        }
    }
  }

  /// 銷毀當前頁面
  popPage() {
    if (Navigator.canPop(context)) { // 檢查Flutter路由棧中,是否還有其他路由
      Navigator.pop(context);
    } else {
      Map<String, int> map = {'age': 12};
      homeMethodChannel.invokeMethod(POP_NOTICE, map);
    }
  }

  /// 前往 Android Personal 頁面
  navAndroidPersonal() {
    Map<String, String> map = {'name': '李四'};
    homeMethodChannel.invokeMethod(NAV_ANDROID_PERSONAL_NOTICE, map);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
          backgroundColor: Colors.blue,
          title: const Text(
            'Flutter Home',
            style: TextStyle(
                fontWeight: FontWeight.w500,
                fontSize: 26,
                color: Colors.yellow),
          )),
      body: SizedBox(
        width: MediaQuery.of(context).size.width,
        height: MediaQuery.of(context).size.height,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Padding(
              padding: const EdgeInsets.only(bottom: 16),
              child: RichText(
                  text: TextSpan(
                      text: '接收初始化參數(shù):',
                      style: const TextStyle(color: Colors.black, fontSize: 20),
                      children: [
                    TextSpan(
                      text: name,
                      style: const TextStyle(color: Colors.red,fontWeight: FontWeight.bold),
                    )
                  ])),
            ),
            Padding(
              padding: const EdgeInsets.only(bottom: 16),
              child: RichText(
                  text: TextSpan(
                      text: '接收上一頁返回參數(shù):',
                      style: const TextStyle(color: Colors.black, fontSize: 20),
                      children: [
                    TextSpan(
                      text: age,
                      style: const TextStyle(color: Colors.red,fontWeight: FontWeight.bold),
                    )
                  ])),
            ),
            Padding(
              padding: const EdgeInsets.only(bottom: 8),
              child: ElevatedButton(
                onPressed: navAndroidPersonal,
                child: const Text(
                  '前往 Android Personal',
                  style: TextStyle(fontSize: 20),
                ),
              ),
            ),
            ElevatedButton(
              onPressed: popPage,
              child: const Text(
                '返回 上一頁',
                style: TextStyle(fontSize: 20),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

login.dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class Login extends StatefulWidget {
  const Login({super.key});

  @override
  State<Login> createState() => _LoginState();
}

class _LoginState extends State<Login> {
  late MethodChannel loginMethodChannel;

  String name = '';

  final String METHOD_CHANNEL_LOGIN = 'com.example.flutter_nav_android/login/method';
  static const String NAV_FLUTTER_LOGIN_NOTICE = 'navFlutterLoginNotice';
  final String POP_NOTICE = 'popNotice';

  @override
  void initState() {
    super.initState();
    loginMethodChannel = MethodChannel(METHOD_CHANNEL_LOGIN);
    loginMethodChannel.setMethodCallHandler(methodHandler);
  }

  /// 監(jiān)聽來自 Android端 的消息通道
  /// Android端調(diào)用了函數(shù),這個handler函數(shù)就會被觸發(fā)
  Future<dynamic> methodHandler(MethodCall call) async {
    final String methodName = call.method;
    switch (methodName) {
      case NAV_FLUTTER_LOGIN_NOTICE: // 進入當前頁面
        {
          name = call.arguments['name'];
          setState(() {});
          return 0;
        }
      default:
        {
          return PlatformException(code: '-1', message: '未找到Flutter端具體實現(xiàn)函數(shù)', details: '具體描述'); // 返回給Android端
        }
    }
  }

  /// 銷毀當前頁面
  popPage() {
    if (Navigator.canPop(context)) { // 檢查Flutter路由棧中,是否還有其他路由
      Navigator.pop(context);
    } else {
      Map<String, int> map = {'age': 28};
      loginMethodChannel.invokeMethod(POP_NOTICE, map);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
          backgroundColor: Colors.blue,
          title: const Text(
            'Flutter Login',
            style: TextStyle(
                fontWeight: FontWeight.w500,
                fontSize: 26,
                color: Colors.yellow),
          )),
      body: SizedBox(
        width: MediaQuery.of(context).size.width,
        height: MediaQuery.of(context).size.height,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Padding(
              padding: const EdgeInsets.only(bottom: 16),
              child: RichText(
                  text: TextSpan(
                      text: '接收初始化參數(shù):',
                      style: const TextStyle(color: Colors.black, fontSize: 20),
                      children: [
                    TextSpan(
                      text: name,
                      style: const TextStyle(color: Colors.red,fontWeight: FontWeight.bold),
                    )
                  ])),
            ),
            ElevatedButton(
              onPressed: popPage,
              child: const Text(
                '返回 上一頁',
                style: TextStyle(fontSize: 20),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

student.dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class Student extends StatefulWidget {
  const Student({super.key});

  @override
  State<Student> createState() => _StudentState();
}

class _StudentState extends State<Student> {

  String title = '';

  static const String METHOD_CHANNEL_STUDENT = 'com.example.flutter_nav_android/student/method';
  static const String NAV_FLUTTER_STUDENT_NOTICE = 'navFlutterStudentNotice';

  @override
  void initState() {
    super.initState();
    MethodChannel bookMethodChannel = const MethodChannel(METHOD_CHANNEL_STUDENT);
    bookMethodChannel.setMethodCallHandler(methodHandler);
  }

  /// 監(jiān)聽來自 Android端 的消息通道
  /// Android端調(diào)用了函數(shù),這個handler函數(shù)就會被觸發(fā)
  Future<dynamic> methodHandler(MethodCall call) async {
    final String methodName = call.method;
    switch (methodName) {
      case NAV_FLUTTER_STUDENT_NOTICE: // 進入當前頁面
        {
          title = call.arguments['title'];
          setState(() {});
          return 0;
        }
      default:
        {
          return PlatformException(
              code: '-1',
              message: '未找到Flutter端具體實現(xiàn)函數(shù)',
              details: '具體描述'); // 返回給Android端
        }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.cyan,
      body: Container(
        width: MediaQuery.of(context).size.width,
        height: MediaQuery.of(context).size.height,
        alignment: Alignment.center,
        child: Text(
          'Flutter $title',
          style: const TextStyle(
            fontWeight: FontWeight.bold,
            color: Colors.white,
            fontSize: 20,
          ),
        ),
      ),
    );
  }

}

main.dart

import 'package:flutter/material.dart';
import 'package:flutter_nav_android/book.dart';
import 'package:flutter_nav_android/student.dart';

import 'home.dart';
import 'login.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
            seedColor: Colors.deepPurple,
         ),
        useMaterial3: true,
      ),
      routes: {
        '/home': (context) => const Home(),
        '/login': (context) => const Login(),
        '/book': (context) => const Book(),
        '/student': (context) => const Student(),
      },
      initialRoute: '/home',
    );
  }
}

踩坑

  • 一個路由坑,F(xiàn)lutter 加載 根命名路由標識,默認是 "?/ ",如果你在Flutter端使用了 "?/ " 作為根路由頁面,有時候,從Android 跳轉(zhuǎn) Flutter頁面時,它會將 根路由頁面 先push進棧,再push你的目標頁面進棧,會多出一個頁面;
  • 所有我直接不用 "?/ "?標識,而使用頁面對應(yīng)的路由標識字符串,來指定根路由。
// 原來帶坑的寫法
// routes: {
//    '/': (context) => const Home(),
//    '/login': (context) => const Login(),
//    '/personal': (context) => const Personal()
// },
// initialRoute: '/',


// 解決方式的寫法
routes: {
    '/home': (context) => const Home(),
    '/login': (context) => const Login(),
    '/personal': (context) => const Personal()
 },
initialRoute: '/home',

奇技淫巧

在案例中,我使用的是 命名路由Channel方式 進行 頁面跳轉(zhuǎn)、傳參,下面直接使用引擎進行 頁面跳轉(zhuǎn)、傳參,但實用價值不高,因為弊端太大;

比如:

  • 只提供了List<String>類型,進行傳參;
  • 目標Flutter頁面內(nèi)的widget,默認參數(shù)會全部失效;
  • Flutter的Widget默認參數(shù),是由主文件內(nèi)的 MaterialApp?組件提供的,一個Flutter應(yīng)用,一般只會使用一個?MaterialApp,它代表返回一個App,如果將目標Flutter頁面套上?MaterialApp?,可以解決這個默認參數(shù)問題,但會引發(fā) 路由問題;
  • 不過也有適用場景:讓每個Flutter頁面完全獨立,之間沒有任何交互,比如跳轉(zhuǎn)、數(shù)據(jù)共享等等,這樣路由就不需要了,讓每個Flutter頁面都使用?MaterialApp,當作App和原生交互;

綜上所述,大家將這種方式當作擴展知識就好了。

Flutter 和 Android原生(Activity、Fragment)相互跳轉(zhuǎn)、傳參,Flutter + Android 混合開發(fā),flutter,android

Android代碼

class MainActivity : AppCompatActivity(), View.OnClickListener {

    ... ... 

    override fun onCreate(savedInstanceState: android.os.Bundle?) {
        super.onCreate(savedInstanceState)

        ... ... 

        val flutterEngine = FlutterEngine(this)

        // 定義參數(shù)
        val dartEntrypointArgs = mutableListOf<String>()
        dartEntrypointArgs.add("張三")

        // 這種方式傳參數(shù),會導致這個Flutter頁面中的Widget默認參數(shù),全部失效,

        // 這種只有 Dart主入口文件,比如main.dart的 main函數(shù)才能接收到參數(shù)
        // void main(List<String args>) {}
        // flutterEngine.dartExecutor.executeDartEntrypoint(
        //    DartExecutor.DartEntrypoint.createDefault(),
        //    dartEntrypointArgs
        // )

        // 這種可以指定頁面接收,但需要在主入口文件里先聲明       
        // void showPersonal(List<String> args) {}
        flutterEngine.dartExecutor.executeDartEntrypoint(
            DartExecutor.DartEntrypoint(
                FlutterInjector.instance().flutterLoader().findAppBundlePath(),
                "showPersonal"), // 找到目標Flutter頁面提供的 暴露函數(shù)
            dartEntrypointArgs)
        FlutterEngineCache.getInstance().put("personal_engine", flutterEngine)
    }


    override fun onClick(v: View?) {
        ... ... 

        val map: MutableMap<String, String> = mutableMapOf<String, String>()
        map["name"] = "張三"
        startActivity(
            FlutterActivity
                .withCachedEngine("personal_engine") // 獲取緩存好的引擎
                .backgroundMode(FlutterActivityLaunchConfigs.BackgroundMode.transparent) // 背景改為透明,不然切換頁面時,會閃爍黑色
                .build(this))
    }

}

Flutter代碼

main.dart(主文件)

import 'package:flutter/material.dart';
import 'package:flutter_nav_android/personal.dart';

void main(List<String> args) {
  debugPrint('args:$args');
  runApp(const MyApp());
}

/// 注解說明文檔:https://mrale.ph/dartvm/compiler/aot/entry_point_pragma.html
/// 注解:表明它可以在 AOT 模式下直接從本機或 VM 代碼解析、分配或調(diào)用
@pragma("vm:entry-point")
void showPersonal(List<String> args) { // 在主文件入口暴露出來
  debugPrint('args:$args');
  runApp(Personal(title: args.first));
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
            seedColor: Colors.deepPurple,
         ),
        useMaterial3: true,
      ),
    );
  }
}

personal.dart(目標頁面)

import 'package:flutter/material.dart';

class Personal extends StatefulWidget {
  final String? title;
  const Personal({super.key,this.title});

  @override
  State<Personal> createState() => _PersonalState();
}

class _PersonalState extends State<Personal> {
  
  /// 在這個頁面中,使用的Widget 默認參數(shù)全部失效

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.white,
      width: MediaQuery.of(context).size.width,
      height: MediaQuery.of(context).size.height,
      alignment: Alignment.center,
      child: Directionality(
          textDirection: TextDirection.ltr,
          child: Text(
            widget.title ?? '',
            style: const TextStyle(
              color: Colors.lightBlue,
              fontSize: 30,
            ),
          )),
    );
  }
}

FlutterEngineGroup

  • 如果你接受以上缺點,可以使用 FlutterEngineGroup,這個東西就是換成了單例寫法,我們自己寫單例,需要處理一個問題,比如這個需求:同時獲取兩個Flutter引擎,這里就要通過判空新建一個Flutter引擎;
  • 而?FlutterEngineGroup 已經(jīng)處理了這個問題,自首個Flutter引擎起,后面多出的Flutter引擎,都是其子類,如果只剩下最后一個,那么這個Flutter引擎將和首個Flutter引擎性能特征相同;
  • FlutterEngineGroup官方文檔:多個 Flutter 頁面或視圖 - Flutter 中文文檔 - Flutter 中文開發(fā)者網(wǎng)站 - Flutter
  • 我個人體驗上來說,不使用單例,性能也足夠了,如果有很多混合的Flutter頁面,那當我沒說??。
  • 沒找到創(chuàng)建子類Flutter引擎的相關(guān)代碼,是從注解中發(fā)現(xiàn)的

Flutter 和 Android原生(Activity、Fragment)相互跳轉(zhuǎn)、傳參,Flutter + Android 混合開發(fā),flutter,android

Debug 和 Release

我用真機做測試,發(fā)現(xiàn)在Debug模式下,第一次從 Android 跳轉(zhuǎn) Flutter 會出現(xiàn)黑屏現(xiàn)象,但?打完包 或在 Release模式?就看不出來了;

我們默認的運行模式就是 Debug模式,可以通過 修改IDE運行命令 --release,切換為?Release模式;

Flutter 和 Android原生(Activity、Fragment)相互跳轉(zhuǎn)、傳參,Flutter + Android 混合開發(fā),flutter,android

Flutter 和 Android原生(Activity、Fragment)相互跳轉(zhuǎn)、傳參,Flutter + Android 混合開發(fā),flutter,android

源碼地址

GitHub - LanSeLianMa/flutter_nav_android: Flutter 和 Android原生(Activity、Fragment)相互跳轉(zhuǎn)、傳參文章來源地址http://www.zghlxwxcb.cn/news/detail-835006.html

到了這里,關(guān)于Flutter 和 Android原生(Activity、Fragment)相互跳轉(zhuǎn)、傳參的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Android adb命令獲取當前Activity或者Fragment

    Android adb命令獲取當前Activity或者Fragment

    用adb命令查看下面Demo處于 NO.3 Fragment 時的 Activity 和 Fragment 信息。 輸出結(jié)果如下: 上面的 com.example.who/com.example.who.ui.activity.SecondActivity} 可以分成兩部分看: / 前的部分是包名, / 后的部分是當前 Activity 的類全名。 該命令會輸出堆棧中全部的窗口信息。 輸出結(jié)果如下, Se

    2024年02月15日
    瀏覽(26)
  • 【Android】怎么使用一個ViewModel用在多個Activity或者Fragment中

    項目需求 在多個Activity或者Fragment中使用同一個ViewModel 需求實現(xiàn) 1.使用ActivityScope或FragmentScope 想在一個Activity或Fragment中共享ViewModel實例,可以使用ActivityScope或FragmentScope。這兩種范圍會根據(jù)它們所綁定的Activity或Fragment自動管理ViewModel實例的生命周期。 例如,創(chuàng)建一個繼承自

    2024年02月15日
    瀏覽(18)
  • uniapp中微信小程序和H5相互跳轉(zhuǎn)及傳參(webview)

    uniapp中微信小程序和H5相互跳轉(zhuǎn)及傳參(webview)

    技術(shù)棧:uniapp-H5+uniapp-微信小程序(vue3+vite2+ts) 前言:在單位做項目的時候碰到一個需求,需要從微信小程序跳轉(zhuǎn)到H5頁面,這兩個端都是使用uniapp編寫的,查資料后決定使用webview來嵌入完成,然后考慮到還可能有參數(shù)(數(shù)據(jù))需要傳遞,所以實現(xiàn)后記錄一下。ps:以下代碼

    2024年02月09日
    瀏覽(85)
  • Android之Fragment 跳轉(zhuǎn)返回重復加載重復執(zhí)行onCreateView的四種解決方法

    前言:? Fragment 跳轉(zhuǎn)返回重復加載重復執(zhí)行 onCreateView 的問題通常是因為 Fragment 生命周期方法的調(diào)用順序和使用不當所導致的。 1,onSaveInstanceState()方法 一種解決方法是在 Fragment 中使用 onSaveInstanceState() 方法保存 Fragment 的狀態(tài),并在 onCreate() 方法中進行狀態(tài)恢復,避免重復執(zhí)

    2024年02月06日
    瀏覽(88)
  • Android Studio中如何在Activity跳轉(zhuǎn)之間傳遞數(shù)據(jù)

    Android Studio中如何在Activity跳轉(zhuǎn)之間傳遞數(shù)據(jù)

    使用Intent操作可以完成兩個Activity之間的跳轉(zhuǎn),有時候也相應(yīng)的需要在兩個跳轉(zhuǎn)活動之間傳遞數(shù)據(jù),這篇就詳細的介紹一些在Android開發(fā)中一些基礎(chǔ)的活動跳轉(zhuǎn)時傳遞數(shù)據(jù)的方法 調(diào)用PutExtra()方法 由于Activity之間的數(shù)據(jù)傳遞有許多不同種類型,所以在Inten類中提供了多個重載的

    2023年04月08日
    瀏覽(34)
  • Android開發(fā)頁面跳轉(zhuǎn)異常且應(yīng)用停止:android.content.ActivityNotFoundException: Unable to find explicit activity

    Android開發(fā)頁面跳轉(zhuǎn)異常且應(yīng)用停止:android.content.ActivityNotFoundException: Unable to find explicit activity

    E/AndroidRuntime: FATAL EXCEPTION: main ??? Process: com.example.app01, PID: 13901 ??? android.content.ActivityNotFoundException: Unable to find explicit activity class {com.example.app01/com.example.app01.RegisterActivity}; have you declared this activity in your AndroidManifest.xml? 根據(jù)日志信息不難發(fā)現(xiàn)問題的所在,就是我們需要將存

    2024年02月16日
    瀏覽(22)
  • adb shell命令查看當前屏幕可見最頂層Activity和Fragment及其調(diào)用棧

    (1)當前屏幕可見頁面最頂層是哪個Activity: (2)當前屏幕可見頁面最頂層是哪個Fragment: (3)當前屏幕可見最頂層Activity及其調(diào)用棧: android adb命令獲取處于當前屏幕的Activity_adb獲取當前頁面activity-CSDN博客 Android adb shell dump當前手機設(shè)備的所有activity_zhangphil的博客-CSDN博客。

    2024年02月07日
    瀏覽(27)
  • flutter和android互相調(diào)用、android原生項目與flutter module之間的交互、如何在flutter module中使用原生的方法

    bridge.dart MainActivity.kt MainActivity中 Flutter中 android項目依賴flutter module的方式網(wǎng)上有很多,這里就不做講解。主要說一下這種情況下android如何與flutter module之間進行方法的調(diào)用 踩坑:期初我是想讓flutter module調(diào)用它內(nèi)部中的.android文件夾下的原生代碼。.android文件夾下有Flutter、

    2023年04月08日
    瀏覽(20)
  • 【flutter和android原生的異步】

    java android 中,是多線程的 1.flutter中不要以為異步就是多線程? 2.flutter的線程隔離理論? UI 線程 : 在 Flutter 中,UI 線程負責處理用戶界面的構(gòu)建和渲染。所有與用戶界面相關(guān)的操作,例如布局計算、繪制和處理用戶輸入等,都在 UI 線程中執(zhí)行。 UI 線程是單線程的,也稱為主

    2024年04月15日
    瀏覽(23)
  • Flutter 頁面嵌入 Android原生 View

    Flutter 頁面嵌入 Android原生 View

    文章主要講解Flutter頁面如何使用Android原生View,但用到了Flutter 和 Android原生 相互通信知識,建議先看完這篇講解 通信的文章 Flutter 與 Android原生 相互通信:BasicMessageChannel、MethodChannel、EventChannel-CSDN博客 數(shù)據(jù)觀察監(jiān)聽,F(xiàn)lutter使用ValueNotifier,Android原生使用LiveData,在實體數(shù)據(jù)

    2024年01月21日
    瀏覽(51)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包