[Flutter] Flutter之Android开发者教程(二)(自译)

文档地址:https://flutter.io/docs/get-started/flutter-for/android-devs

译者:Haocxx

Intent

在Flutter中,Intent等于什么?

    在Android中,Intent主要有两个作用:在不同Activity之间跳转,以及组件之间的通信。在Flutter中其实并没有Intent的概念,即使你仍然可以集成使用一个AndroidIntent的插件(https://pub.dartlang.org/packages/android_intent)。

    Flutter中并没有那么多的Activity和Fragment,如果要跳转页面的话,是通过Navigator和Route来实现的。

    Route是对一个APP页面的抽象,而Navigator是管理Route的组件,一个Route可以认为对应了一个Activity。Navigator可以通过pop和push来讲Route移入或移出屏幕。Navigator就像一个栈一样,你可以调用push()来将你想要跳转的Route移入栈顶,也可以调用pop()将栈顶的Route移出(比如返回键的逻辑)。

    在Android中,Acitivity被生命在AndroidManifest.xml文件中.

    在Flutter中,可以用两步来实现页面的跳转:首先定义一个Route的Map表,然后就可以通过Navigator直接跳转了。

    如下定义一个Route Map:

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

    通过向Navigator传递一个Route的name key来跳转页面:

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

    Intent还有其他用法比如调用像相机,文件选择器之类的外部组件。对于这种实现,你需要创建一个native集成或使用已有的库。具体方法参见:https://flutter.io/docs/development/packages-and-plugins/developing-packages

如何在Flutter中处理外部应用传入的Intent?

    Flutter可以通过直接与Android应用层通信并获取Intent中的信息来处理从Android原生中传入的Intent。

    下面的例子中,为运行在Flutter下的Android原生Activity注册了一个文本共享的intent-filter,其他的APP可以与我们的Flutter APP共享文本。

    这个程序的基本流程是先在Android原生端处理文本数据,然后等待Flutter请求数据,通过MethodChannel发送。

    首先,在AndroidManifest里面注册intent-filter:

<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">
  <!-- ... -->
  <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中处理数据,持有Intent中的text数据。当Flutter准备就绪,就可以通过native方法来获取数据了:

package com.example.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 {

  private 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 MethodCallHandler() {
        @Override
        public void onMethodCall(MethodCall call, MethodChannel.Result result) {
          if (call.method.contentEquals("getSharedText")) {
            result.success(sharedText);
            sharedText = null;
          }
        }
      });
  }

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

    最后,在Flutter的Widget渲染的时候去请求数据:

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

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

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

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

  @override
  _SampleAppPageState createState() => _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 Scaffold(body: Center(child: Text(dataShared)));
  }

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

在Flutter中,如何实现startActivityForResult的效果?

    在Flutter中,Navigator类在跳转Route,push到栈时可以获取一个返回值,由push()方法返回。

    比如,跳转一个叫“/location”的Route让用户选择位置信息,可以这样做:

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

    然后,在选择位置Route当中,在用户选定了位置之后,可以这样讲Route移出栈并返回结果:

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值