美文网首页
Flutter与android的对比---Intents

Flutter与android的对比---Intents

作者: 韩明泽 | 来源:发表于2019-01-08 10:22 被阅读30次

本文是在GitHub上一个flutter项目的资料中看到的,由于原文过于太长,因此对其进行了章节拆分方便阅读,此篇为原文的部分内容,后续内容会在今后陆续更新完;如果想查看该项目请跳转GitHub查看。

注:GitHub的这篇资料是转载的flutter中文官网的文章,这里是原文地址。

Intents

  • Android 中的 Intent 在 Flutter 中对应什么?
  • 在 Flutter 中如何处理来自外部的 Intent ?
  • startActivityForResult 在 Flutter 中如何实现?

Android 中的 Intent 在 Flutter 中对应什么?

在 Android 中 Intent 主要有两种用途:在 Activity 之间切换和调用外部组件。Flutter 中没有 Intent 的概念,但如果需要的话 Flutter 可以通过插件的方式间接使用 Intent。

在 Flutter 中切换界面可以通过 Route 来实现。另外值得注意的是在管理 Flutter 中的多个界面的时候有两个重要的概念:RouteNavigator。一个 Route 就代表了一个界面(类似与 Activity),而 Navigator 则是一个管理 Route 的 Widget。Navigator 可以通过 poppush 的方法在界面之间进行切换。

类似 Android 中可以在 AndroidManifest 中定义 Activity,在 Flutter 中可以将指定 Route 的映射集合添加到 MaterialApp 的根目录。

void main() {
  runApp(new MaterialApp(
    home: new MyAppHome(), // becomes the route named '/'
    routes: <String, WidgetBuilder> {
      '/a': (BuildContext context) => new MyPage(title: 'page A'),
      '/b': (BuildContext context) => new MyPage(title: 'page B'),
      '/c': (BuildContext context) => new MyPage(title: 'page C'),
    },
  ));
}

接着就可以通过如下方式来操作 Route。

    Navigator.of(context).pushNamed('/b');

Intent 另外一个比较实用的作用是调用外部组件,如 Camera 或文件选择器,如果要在 Flutter 中实现类似功能,你需要在平台代码中集成现有的库或重新实用。

查看 开发扩展包 章节查看如何集成平台本地功能。

在 Flutter 中如何处理来自外部的 Intent ?

Flutter 可以和 Android 层进行交互来共享传入的 Intent。

在下面的例子中,我们在 AndroidManifest.xml 中注册了发送文本的 Intent 过滤器,然后 App 的 Android 层就可以与 Flutter 层共享传入的文本。

下面例子的基本流程是首先我们处理 Android 层 Intent 传入的数据,然后当 Flutter 层发送请求时将文本通过 MethodChannel 传递给 Flutter 层。

首先在 AndroidManifest.xml 中注册 Intent。

<activity
    android:name=".MainActivity"
    android:launchMode="singleTop"
    android:theme="@style/LaunchTheme"
    android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
    android:hardwareAccelerated="true"
    android:windowSoftInputMode="adjustResize">
    <!-- This keeps the window background of the activity showing
        until Flutter renders its first frame. It can be removed if
        there is no splash screen (such as the default splash screen
        defined in @style/LaunchTheme). -->
    <meta-data
       android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
       android:value="true" />
    <intent-filter>
       <action android:name="android.intent.action.MAIN"/>
       <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
    <intent-filter>
       <action android:name="android.intent.action.SEND" />
       <category android:name="android.intent.category.DEFAULT" />
       <data android:mimeType="text/plain" />
    </intent-filter>
</activity>

接着在 MainActivity 中处理接收到的文本信息并保存下来,当 Flutter 层请求文本信息时将其传递给 Flutter 层即可。

package com.yourcompany.shared;

import android.content.Intent;
import android.os.Bundle;

import java.nio.ByteBuffer;

import io.flutter.app.FlutterActivity;
import io.flutter.plugin.common.ActivityLifecycleListener;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugins.GeneratedPluginRegistrant;

public class MainActivity extends FlutterActivity {
    String sharedText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        GeneratedPluginRegistrant.registerWith(this);
        Intent intent = getIntent();
        String action = intent.getAction();
        String type = intent.getType();

        if (Intent.ACTION_SEND.equals(action) && type != null) {
            if ("text/plain".equals(type)) {
                handleSendText(intent); // Handle text being sent
            }
        }

        new MethodChannel(getFlutterView(), "app.channel.shared.data").setMethodCallHandler(new MethodChannel.MethodCallHandler() {
            @Override
            public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
                if (methodCall.method.contentEquals("getSharedText")) {
                    result.success(sharedText);
                    sharedText = null;
                }
            }
        });
    }


    void handleSendText(Intent intent) {
        sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
    }
}

最后在 Flutter 层,可以选择在 initState 中对文本进行请求。

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

void main() {
  runApp(new SampleApp());
}

class SampleApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Sample Shared App Handler',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new SampleAppPage(),
    );
  }
}

class SampleAppPage extends StatefulWidget {
  SampleAppPage({Key key}) : super(key: key);

  @override
  _SampleAppPageState createState() => new _SampleAppPageState();
}

class _SampleAppPageState extends State<SampleAppPage> {
  static const platform = const MethodChannel('app.channel.shared.data');
  String dataShared = "No data";

  @override
  void initState() {
    super.initState();
    getSharedText();
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(body: new Center(child: new Text(dataShared)));
  }

  getSharedText() async {
    var sharedData = await platform.invokeMethod("getSharedText");
    if (sharedData != null) {
      setState(() {
        dataShared = sharedData;
      });
    }
  }
}

startActivityForResult 在 Flutter 中如何实现?

可以通过 Navigator 的 push 方法返回的 Futrue 来获得页面的返回数据。

例如你想启动一个地点选择的界面,然后从中获得用户选择的结果,可以使用如下方法:

Map coordinates = await Navigator.of(context).pushNamed('/location');

接着在地点选择界面,当用户选择完位置以后,可以调用如下方法把结果传递给上面的 coordinates

Navigator.of(context).pop({"lat":43.821757,"long":-79.226392});

相关文章

网友评论

      本文标题:Flutter与android的对比---Intents

      本文链接:https://www.haomeiwen.com/subject/yvcvrqtx.html