flutter access to the existing app, detailed introduction, large factory Interview Questions Summary

Of course, the process I mentioned above is quite smooth, but my access process is not so smooth. I will try all kinds of. 1. For example, we don't go to fluent create - t module my in the same level directory of Android project_ What happens to flutter? I tried. Just add your project directory name to the path. Write it like this

setBinding(new Binding([gradle: this]))                                 // new
evaluate(new File(                                                      // new
        settingsDir.parentFile,                                               // new
        'Your project directory name/tip_flutter/.android/include_flutter.groovy'                          // new
)) 

ok, but it's not elegant. When ios introduces this fluent module, you need to find it in your android project. Therefore, it will be more elegant and physically decoupled independent of android project. 2. Some small partners may have configured buildTypes. Of course, synchronization must fail. The solution is to modify build.gradle in the shuttle directory of your. android directory. Just keep consistent with the buildTypes of your app.

3. debug runs very well and release kneels. This must be a problem of confusion. You can refer to it

-keep class io.flutter.app.** { *; }
-keep class io.flutter.plugin.**  { *; }
-keep class io.flutter.util.**  { *; }
-keep class io.flutter.view.**  { *; }
-keep class io.flutter.**  { *; }
-keep class io.flutter.plugins.**  { *; } 

4,Libshuttle.so not found This is obviously not loaded into the so library supported by the corresponding cpu architecture. Please Refer here , someone directly

ndk {
                abiFilters "armeabi","armeabi-v7a". . . . Add everything. Can you stand your big bag.
            } 

In conclusion, in fact, the access process is not so smooth. Ha ha, there are still many pits, but generally solutions can be found.

Use posture

There are two ways for native modules to pull up the fluent module: 1. Directly create a fluent view and add it to your layout, route1 here.

View flutterView = Flutter.createView(
      MainActivity.this,
      getLifecycle(),
      "route1"
    );
    FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(600, 800);
    layout.leftMargin = 100;
    layout.topMargin = 200;
    addContentView(flutterView, layout); 

I believe you don't know what it is at the beginning. This is actually a way for flutter to manage pages. You can configure routes for each page by using routing processing. Here route1 represents the name of that page, so you can directly jump to the page named route1. If you write "/", you will directly jump to the page of main.dart. Continue to study here, Why does "/" jump to main? That's because the sentence void main() = > runapp (New myapp());, Understandably, he is a root. 2. How to use fragment

FragmentTransaction tx = getSupportFragmentManager().beginTransaction();
   tx.replace(R.id.someContainer, Flutter.createFragment("route1"));
   tx.commit(); 

Well, the above are the two ways in which the element module applies the flutter module. In fact, you will find that it is just one kind. Both of them add a flutterView to the native. Looking at the source code, you will find that the flutterView is actually a SurfaceView, but implements a special interface BinaryMessenger.

flutter calls the native module

It's very simple to open a page implemented by fluent, but where does the data displayed come from? There are usually two ways. A and native send data to the shuttle. b. The fluent end requests data from the native end. Here, let's first look at the second one. The fluent side asks for data from the native side, because the second one is mentioned more officially. Usually, the native way of calling the fluent is through the MethodChannel. Let's learn how to do it first.

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

Let's take a look at the source code definition. Here's the interception part

public final class MethodChannel {
    private static final String TAG = "MethodChannel#";
    private final BinaryMessenger messenger;
    private final String name;
    private final MethodCodec codec;

    public MethodChannel(BinaryMessenger messenger, String name) {
        this(messenger, name, StandardMethodCodec.INSTANCE);
    } 

As mentioned earlier, the first parameter is BinaryMessenger. Since FlutterView implements this interface, getFlutterView() is passed in the official demo.

Well, obviously, the chapter on using posture mentioned earlier introduces two methods. The first method, fluterview, is obviously there. You can easily get it and start a MethodChannel. What about the second way? Don't worry. Look what the FlutterFragment is.

public class FlutterFragment extends Fragment {
  public static final String ARG_ROUTE = "route";
  private String mRoute = "/";

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (getArguments() != null) {
      mRoute = getArguments().getString(ARG_ROUTE);
    }
  }

  @Override
  public void onInflate(Context context, AttributeSet attrs, Bundle savedInstanceState) {
    super.onInflate(context, attrs, savedInstanceState);
  }

  @Override
  public FlutterView onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return Flutter.createView(getActivity(), getLifecycle(), mRoute);
  }
} 

It's easy to open it. onCreateView actually returns a FlutterView, which is mentioned earlier. In fact, the native reference to the flutter module is just adding a FlutterView to the existing layout.

OK, after clarifying the two methods, let me introduce the specific operation in the form of the second method.

public class FlutterBaseFragment extends FlutterFragment {

    private static final String METHOD_CHANNEL = "tip.flutter.io/method";

    public static FlutterBaseFragment newInstance(String route) {

        Bundle args = new Bundle();
        args.putString(ARG_ROUTE, route);
        FlutterBaseFragment fragment = new FlutterBaseFragment();
        fragment.setArguments(args);
        return fragment;
    }
    @SuppressWarnings("unchecked")
    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        new MethodChannel((FlutterView) getView(), METHOD_CHANNEL).setMethodCallHandler(
                new MethodChannel.MethodCallHandler() {
                    @Override
                    public void onMethodCall(MethodCall call, final MethodChannel.Result result) {
                        if (call.method.equals("getBatteryLevel")) {
                            int batteryLevel = getBatteryLevel();

                            if (batteryLevel != -1) {
                                result.success(batteryLevel);
                            } else {
                                result.error("UNAVAILABLE", "Battery level not available.", null);
                            }
                        } else {
                            result.notImplemented();
                        }
                    }
                });
    }

    private int getBatteryLevel() {...}
} 

The above is the implementation of the native part. Then, how to call the fluent?

class _MyHomePageState extends State<MyHomePage> {
  static const platform = const MethodChannel('tip.flutter.io/method');
  String _batteryLevel = 'Unknown battery level.';

  Future<Null> _getBatteryLevel() async {
    String batteryLevel;
    try {
      final int result = await platform.invokeMethod('getBatteryLevel');
      batteryLevel = 'Battery level at $result % .';
    } on PlatformException catch (e) {
      batteryLevel = "Failed to get battery level: '${e.message}'.";
    }

    setState(() {
      _batteryLevel = batteryLevel;
    });
  } 

Very familiar. This is just the official demo.

Then, is there no requirement for the data sent to fluent through MethodChannel? Can any type of data be sent? Sorry, it's not. For example, your custom class is obviously not allowed. He supports only the following types:

[external chain picture transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-nksat1or-1630518123060)( https://user-gold-cdn.xitu.io/2018/8/14/16537df4e35280d6? imageView2/0/w/1280/h/960/ignore-error/1)]

so, what should we do in the past when we want to send custom type data?

Obviously, we need to convert to the type supported by dart. Maybe you think of object - > Json, and then go to the shuttle and change it to a Json object. However, there are other ways. For example, if you happen to use protobuf, it must be good to send byte [] directly. In addition, you can also implement a custom protocol if you have enough time. In short, the transmitted data needs to be of a type that can be recognized between platforms.

Send data to native flutter

It feels strange to send data to the flutter by native. So, what is the specific scene? For example, is it easy to understand? OK, for example, how to convey the change of mobile phone charging state to the flutter?

At this time, you need to use the EventChannel. In fact, it is no different from the way the MethodChannel sent data in the past. However, we understand that the MethodChannel is an active request from the shuttle side and obtained the data, while the EventChannel may be understood as being pushed from the native initiative.

Epilogue

For many junior and intermediate Android engineers, if they want to improve their skills, they often grope and grow by themselves. The learning effect of fragmentation is inefficient, long and helpless. These architecture technologies hope to be a reference for Android development friends and avoid detours. The focus of this article is whether you have gained and grown, and the rest are not important. I hope readers can keep this in mind.

Finally, if you want to get a high salary, improve your technology and get a qualitative leap in salary. The quickest way is that someone can take you to analyze together, which is the most efficient way to learn. Therefore, in order for you to smoothly advance to middle and senior architects, I specially prepared a set of high-quality Android architect courses such as source code and framework video for you to learn, so as to ensure that your salary will rise to a higher level after you learn.

  • Mind map
  • Performance optimization learning notes


  • Performance optimized video

    When you have a learning route, what to learn, and know how to go in the future, you always have to practice when you see too much theory.
    mg-1XGoQarH-1630518123067)]

[external chain picture transferring... (img-VQr8NhOc-1630518123069)]
[external chain picture transferring... (IMG pcyatqtk-1630518123070)]

Tags: Android Design Pattern Interview Flutter

Posted on Wed, 01 Sep 2021 13:10:26 -0400 by ez5527