How do you pass the MethodChannel Result to a new

2019-08-25 07:59发布

问题:

fellow Flutter enthusiasts, pros, and future friends. I've been really banging my head from trying to pass the MethodChannel.Result from the MainActivity to a new activity (to handle the result handler after performing some work there).

In iOS, I've stuffed the FlutterResult into a struct with other pertinent values and passed that into a new ViewController, and have been successfully running the result handler from there.

How do I go about doing so in Android? Since the result isn't serializable I can't add it as an extra in an intent.

In my MainActivity, I'm running 'setMethodCallHandler', and in the proper call.method case, I'm creating a new intent and starting it. I'm successful adding in and pulling out String values in the new activity but it's that Flutter Result that I'm needing to pass over.

What is the recommended way to achieve this? Am I going about it the wrong way?

I ask if I'm doing it incorrectly because when I finish() this new activity, there is a half-second black screen that takes over the screen when the activity is dismissed.

Not sure if it matters, but I'm writing in Kotlin. I would be happy to hear any Java recommendations though.

Thank you all in advance.

回答1:

Without a little bit more context about what exactly you're doing in the new activity, it's a little bit hard to tell why you'd be getting a black screen. Theoretically, the flutter activity should still be running and should show up when you finish the new activity - unless you're doing something blocking on the UI thread.

However, for passing the result - what you want to be doing is to keep a reference to the result handler wherever you're receiving the message from flutter, and making use of android's startActivityForResult method. See the android docs on getting a result from an activity. Your 'worker' activity should do whatever it needs to do, then pass the result back by calling setResult before finish. The data you pass back must be serializable.

There is a slight added wrinkle - you're not necessarily working with your own activity here (if you're writing a plugin anyways). If that's the case, you'll need to implement ActivityResultListener and call registrar.addActivityResultListener in your plugin's registerWith function. If you're just doing this in an app, you can simply override onActivityResult - just make sure to call super or you might break other flutter plugins.

There is another possible solution to this, with various levels of hacky-ness depending on how in-depth you want to be. The solution is to simply use a Singleton or Global to store what you need between activities. For anyone out there who's reading this - I don't endorse doing this, I'm just providing an alternative. There are caveats to go with this - among them is that globals and to a lesser extent singletons are seen to be a bad idea for many reasons, among them code maintainability. If you absolutely must go down this route, I suggest using a Registry pattern rather than a simple singleton - i.e. you create a key that is serializable and store the Result in essentially a global/singleton map using the key, pass the key to the new activity, then in the new activity retrieve the value with that key (and make sure to remove the object from the map).

Note that the global/singleton/registry option won't work properly if the app is stopped by android as the activity could be recreated from its intent, but the object in memory may not persist. Then again - the flutter callback won't persist anyways so that point might be moot anyways.

If you're still seeing the black screen after finishing the new activity, that sounds more like a bug or something to do with the implementation of your new activity than a flutter problem.