-
Notifications
You must be signed in to change notification settings - Fork 3.6k
[camerax] Update instance manager and replace Java 8 language usages with Java 7 #3318
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| /// This is typically only used after a hot restart. | ||
| void clear(); | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bparrishMines I'm using this PR to do some cleanup I need to do to match the internal plugin and use your updated instance manager. I was wondering where this is used? As the comment suggests, I figured this was used for hot restart, but I didn't see it used in your example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's used in the initial creation of BaseObject.globalInstanceManager: https://github.com/bparrishMines/packages/blob/wrapper_example/packages/wrapper_example/lib/src/base_object.dart#L74.
This should translate to be used by your JavaObject class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would also note that this also breaks some tests. So I had to mock the host api in the tests:
@GenerateMocks(<Type>[TestInstanceManagerHostApi])
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
// Mocks the call to clear the native InstanceManager.
TestInstanceManagerHostApi.setup(MockTestInstanceManagerHostApi());
...
bparrishMines
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is also missing the implementation in the Java plugin class https://github.com/bparrishMines/packages/blob/wrapper_example/packages/wrapper_example/android/src/main/java/com/example/wrapper_example/WrapperExamplePlugin.java#L26
| CameraSelector.Builder cameraSelectorBuilder = cameraXProxy.createCameraSelectorBuilder(); | ||
| CameraSelector cameraSelector; | ||
|
|
||
| if (lensFacing != null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about rearranging this code to the following.
CameraSelector.Builder cameraSelectorBuilder = cameraXProxy.createCameraSelectorBuilder();
if (lensFacing != null) {
cameraSelectorBuilder = cameraSelectorBuilder.requireLensFacing(lensFacing.intValue());
}
instanceManager.addDartCreatedInstance(cameraSelectorBuilder.build(), identifier);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you decide not to do this?
...camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/InstanceManager.java
Outdated
Show resolved
Hide resolved
...camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/InstanceManager.java
Outdated
Show resolved
Hide resolved
| private static final String CLOSED_WARNING = "Method was called while the manager was closed."; | ||
|
|
||
| /** Interface for listening when a weak reference of an instance is removed from the manager. */ | ||
| public interface FinalizationListener { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This class looks like it has to check if the manager is closed in every method. That design pattern of requiring work in every method can be dangerous/tedious. It appears that each method has bespoke error conditions so that makes building a helper more difficult but here are some suggestions I would like you to consider.
- Class method structure:
For every public method make a private method of the same name. The only logic in public methods is the check for close and error return value.
As an example
public boolean containsInstance(Object instance) {
if (isClosed()) {
Log.w(TAG, CLOSED_WARNING);
return false;
}
return constainsInstanceUnsafe(instance);
}
// Probably a bad name.
private boolean constainsInstanceUnsafe(Object instance) {
return identifiers.containsKey(instance)
}
- Change the method definitions to only return the expected values and throw a typed error when the instance is called. This requires callers to catch the error but can make this class easier to maintain. This may or may not be combined with the first suggestion. What is nice this this behavior can be contained in a method and documentation added that says that every class in this method must call
verifyNotClosed()first. - Something else
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bparrishMines what do you think about these alternatives?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Class method structure:
For every public method make a private method of the same name. The only logic in public methods is the check for close and error return value.
I don't see how this is much different than the current structure. It just moves the method logic to a private class. Is it not dangerous/tedious for the same reason?
- Change the method definitions to only return the expected values and throw a typed error when the instance is called. This requires callers to catch the error but can make this class easier to maintain. This may or may not be combined with the first suggestion. What is nice this this behavior can be contained in a method and documentation added that says that every class in this method must call verifyNotClosed() first.
To verify, this is suggesting throwing a checked exception when closed? This could be a good alternative solution, but it would require adding a try/catch block in a lot of places. InstanceManager is used extensively in this design, so this would require majority of the methods of all the other classes to use a try/catch.
I do like the suggestion of verifyNotClosed. What do you think of adding something like the method below and require it in every method. This would at least reduce the need to log in every method.
private boolean assertNotClosed() {
if (isClosed()) {
Log.w(TAG, CLOSED_WARNING);
return true;
}
return false;
}Although checking the closed state in every method is not easy to maintain, this class is only really changed when fixing bugs. I don't see many reasons to add more than a few methods to it based on the small scope of the class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@reidbaker Looking to land this so I can make progress elsewhere. Can you file an issue for this or discuss it here, but approve this PR for now? I can make any changes in a follow up PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"I don't see how this is much different than the current structure. It just moves the method logic to a private class. Is it not dangerous/tedious for the same reason?"
Yes it is but at least the structure of the code makes it obvious that it is a design pattern. I am not sure the same is obvious with the current reading of the code.
"To verify, this is suggesting throwing a checked exception when closed? This could be a good alternative solution, but it would require adding a try/catch block in a lot of places. " yes I tried to call that out in "This requires callers to catch the error but can make this class easier to maintain."
The difficulties in this class are the result of InstanceManager exporting the need to check if it is closed first. I am not sure if that means it is either an acceptable burden to continue the cost up the tree or if it means that InstanceManager should be refactored to remove the need to check if closed before any interaction.
@camsim99 can you find 30 minutes for you me and @bparrishMines to talk about this. I think the current structure is risky to maintain. I will approve the pr as is since most of this update is unrelated.
...ra_android_camerax/android/src/test/java/io/flutter/plugins/camerax/InstanceManagerTest.java
Outdated
Show resolved
Hide resolved
bparrishMines
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
packages/camera/camera_android_camerax/lib/src/instance_manager.dart
Outdated
Show resolved
Hide resolved
packages/camera/camera_android_camerax/lib/src/instance_manager.dart
Outdated
Show resolved
Hide resolved
packages/camera/camera_android_camerax/lib/src/java_object.dart
Outdated
Show resolved
Hide resolved
|
auto label is removed for flutter/packages, pr: 3318, due to This PR has not met approval requirements for merging. Changes were requested by {reidbaker}, please make the needed changes and resubmit this PR.
|
|
auto label is removed for flutter/packages, pr: 3318, due to - This pull request has changes requested by @reidbaker. Please resolve those before re-applying the label. |
| CameraSelector.Builder cameraSelectorBuilder = cameraXProxy.createCameraSelectorBuilder(); | ||
| CameraSelector cameraSelector; | ||
|
|
||
| if (lensFacing != null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you decide not to do this?
| private static final String CLOSED_WARNING = "Method was called while the manager was closed."; | ||
|
|
||
| /** Interface for listening when a weak reference of an instance is removed from the manager. */ | ||
| public interface FinalizationListener { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"I don't see how this is much different than the current structure. It just moves the method logic to a private class. Is it not dangerous/tedious for the same reason?"
Yes it is but at least the structure of the code makes it obvious that it is a design pattern. I am not sure the same is obvious with the current reading of the code.
"To verify, this is suggesting throwing a checked exception when closed? This could be a good alternative solution, but it would require adding a try/catch block in a lot of places. " yes I tried to call that out in "This requires callers to catch the error but can make this class easier to maintain."
The difficulties in this class are the result of InstanceManager exporting the need to check if it is closed first. I am not sure if that means it is either an acceptable burden to continue the cost up the tree or if it means that InstanceManager should be refactored to remove the need to check if closed before any interaction.
@camsim99 can you find 30 minutes for you me and @bparrishMines to talk about this. I think the current structure is risky to maintain. I will approve the pr as is since most of this update is unrelated.
| * @return the unique identifier stored with instance. | ||
| * @param instance the instance to be stored. This must be unique to all other added instances. | ||
| * @return the unique identifier (>= 0) stored with instance. If the manager is closed, returns | ||
| * -1. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You probably want to update this value to say that it returns INSTANCE_CLOSED not -1.
… usages with Java 7 (flutter/packages#3318)
… usages with Java 7 (flutter/packages#3318)
… usages with Java 7 (flutter/packages#3318)
…with Java 7 (flutter#3318) [camerax] Update instance manager and replace Java 8 language with Java 7
Replaces the instance manager with the updated on from @bparrishMines's https://github.com/bparrishMines/plugins/tree/wrapper_example/packages/wrapper_example and fixes a casting issue that requires Java 8, causing a problem internally.
Pre-launch Checklist
dart format.)[shared_preferences]pubspec.yamlwith an appropriate new version according to the pub versioning philosophy, or this PR is exempt from version changes.CHANGELOG.mdto add a description of the change, following repository CHANGELOG style.///).