Add API for synchronous rendering to Panel
This commit is contained in:
		| @@ -21,8 +21,12 @@ import android.content.Context; | ||||
| import android.content.Intent; | ||||
| import android.text.TextUtils; | ||||
|  | ||||
| import com.github.pengfeizhou.jscore.ArchiveException; | ||||
| import com.github.pengfeizhou.jscore.JSArray; | ||||
| import com.github.pengfeizhou.jscore.JSDecoder; | ||||
| import com.github.pengfeizhou.jscore.JSONBuilder; | ||||
| import com.github.pengfeizhou.jscore.JSObject; | ||||
| import com.github.pengfeizhou.jscore.JSValue; | ||||
|  | ||||
| import org.json.JSONObject; | ||||
|  | ||||
| @@ -44,6 +48,7 @@ import pub.doric.navbar.IDoricNavBar; | ||||
| import pub.doric.navigator.IDoricNavigator; | ||||
| import pub.doric.performance.DoricPerformanceProfile; | ||||
| import pub.doric.plugin.DoricJavaPlugin; | ||||
| import pub.doric.plugin.ShaderPlugin; | ||||
| import pub.doric.resource.DoricResource; | ||||
| import pub.doric.shader.RootNode; | ||||
| import pub.doric.shader.ViewNode; | ||||
| @@ -383,4 +388,50 @@ public class DoricContext { | ||||
|     public void releaseJavaValue(SoftReference<RetainedJavaValue> retainedJavaValue) { | ||||
|         retainedJavaValues.remove(retainedJavaValue); | ||||
|     } | ||||
|  | ||||
|     public AsyncResult<JSDecoder> pureCallEntity(String methodName, Object... args) { | ||||
|         final AsyncResult<JSDecoder> asyncResult = new AsyncResult<>(); | ||||
|         final Object[] nArgs = new Object[args.length + 2]; | ||||
|         nArgs[0] = getContextId(); | ||||
|         nArgs[1] = methodName; | ||||
|         if (args.length > 0) { | ||||
|             System.arraycopy(args, 0, nArgs, 2, args.length); | ||||
|         } | ||||
|         getDriver().invokeDoricMethod(DoricConstant.DORIC_CONTEXT_INVOKE_PURE, nArgs).setCallback(new AsyncResult.Callback<JSDecoder>() { | ||||
|             @Override | ||||
|             public void onResult(JSDecoder result) { | ||||
|                 asyncResult.setResult(result); | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public void onError(Throwable t) { | ||||
|                 getDriver().getRegistry().onException(DoricContext.this, t instanceof Exception ? (Exception) t : new RuntimeException(t)); | ||||
|                 asyncResult.setError(t); | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public void onFinish() { | ||||
|  | ||||
|             } | ||||
|         }); | ||||
|         return asyncResult; | ||||
|     } | ||||
|  | ||||
|     public void renderSynchronously() { | ||||
|         AsyncResult<JSDecoder> asyncResult = pureCallEntity(DoricConstant.DORIC_ENTITY_FETCH_DIRTY_DATA); | ||||
|         JSDecoder jsDecoder = asyncResult.synchronous().get(); | ||||
|         DoricJavaPlugin shaderPlugin = obtainPlugin(getDriver().getRegistry().acquirePluginInfo("Shader")); | ||||
|         try { | ||||
|             JSValue result = jsDecoder.decode(); | ||||
|             if (shaderPlugin instanceof ShaderPlugin && result.isArray()) { | ||||
|                 JSArray jsArray = result.asArray(); | ||||
|                 for (int i = 0; i < jsArray.size(); i++) { | ||||
|                     JSObject model = jsArray.get(i).asObject(); | ||||
|                     ((ShaderPlugin) shaderPlugin).render(model, null); | ||||
|                 } | ||||
|             } | ||||
|         } catch (ArchiveException e) { | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -29,6 +29,7 @@ import com.github.pengfeizhou.jscore.JavaValue; | ||||
| import java.lang.reflect.Method; | ||||
| import java.util.concurrent.Callable; | ||||
|  | ||||
| import androidx.annotation.Nullable; | ||||
| import pub.doric.DoricContext; | ||||
| import pub.doric.async.AsyncResult; | ||||
| import pub.doric.extension.bridge.DoricMethod; | ||||
| @@ -54,7 +55,7 @@ public class ShaderPlugin extends DoricJavaPlugin { | ||||
|     } | ||||
|  | ||||
|     @DoricMethod(thread = ThreadMode.UI) | ||||
|     public void render(final JSObject jsObject, final DoricPromise promise) { | ||||
|     public void render(final JSObject jsObject, @Nullable final DoricPromise promise) { | ||||
|         final DoricPerformanceProfile profile = getDoricContext().getPerformanceProfile(); | ||||
|         profile.prepare(DoricPerformanceProfile.STEP_RENDER); | ||||
|         getDoricContext().getDriver().asyncCall(new Callable<Object>() { | ||||
| @@ -90,8 +91,10 @@ public class ShaderPlugin extends DoricJavaPlugin { | ||||
|                         targetView.post(new Runnable() { | ||||
|                             @Override | ||||
|                             public void run() { | ||||
|                                 if (promise != null) { | ||||
|                                     promise.resolve(); | ||||
|                                 } | ||||
|                             } | ||||
|                         }); | ||||
|                     } | ||||
|                 }); | ||||
|   | ||||
| @@ -76,4 +76,5 @@ public class DoricConstant { | ||||
|     public static final String DORIC_ENTITY_HIDDEN = "__onHidden__"; | ||||
|     public static final String DORIC_ENTITY_BUILD = "__build__"; | ||||
|     public static final String DORIC_ENTITY_ENV_CHANGE = "__onEnvChanged__"; | ||||
|     public static final String DORIC_ENTITY_FETCH_DIRTY_DATA = "__fetchEffectiveData__"; | ||||
| } | ||||
|   | ||||
| @@ -68,11 +68,15 @@ NS_ASSUME_NONNULL_BEGIN | ||||
|  | ||||
| - (void)onHidden; | ||||
|  | ||||
| -(void)onEnvChanged; | ||||
| - (void)onEnvChanged; | ||||
|  | ||||
| - (DoricViewNode *)targetViewNode:(NSString *)viewId; | ||||
|  | ||||
| - (void)dispatchToMainQueue:(_Nonnull dispatch_block_t)block; | ||||
|  | ||||
| - (DoricAsyncResult *)pureCallEntity:(NSString *)method withArgumentsArray:(NSArray *)args; | ||||
|  | ||||
| - (void)renderSynchronously; | ||||
| @end | ||||
|  | ||||
| NS_ASSUME_NONNULL_END | ||||
|   | ||||
| @@ -28,6 +28,8 @@ | ||||
| #import "DoricNativeDriver.h" | ||||
| #import "DoricUtil.h" | ||||
| #import "DoricSingleton.h" | ||||
| #import "DoricShaderPlugin.h" | ||||
| #import <JavaScriptCore/JavaScriptCore.h> | ||||
| 
 | ||||
| @implementation DoricContext | ||||
| 
 | ||||
| @@ -154,4 +156,36 @@ - (void)dispatchToMainQueue:(_Nonnull dispatch_block_t)block { | ||||
|         } | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| - (DoricAsyncResult *)pureCallEntity:(NSString *)method withArgumentsArray:(NSArray *)args { | ||||
|     NSMutableArray *array = [[NSMutableArray alloc] init]; | ||||
|     [array addObject:self.contextId]; | ||||
|     [array addObject:method]; | ||||
|     [array addObjectsFromArray:args]; | ||||
|     DoricAsyncResult *ret = [self.driver invokeDoricMethod:DORIC_CONTEXT_INVOKE_PURE argumentsArray:array]; | ||||
|     __weak typeof(self) __self = self; | ||||
|     ret.exceptionCallback = ^(NSException *e) { | ||||
|         __strong typeof(__self) self = __self; | ||||
|         [self.driver.registry | ||||
|                 onException:e | ||||
|                   inContext:self]; | ||||
|     }; | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| - (void)renderSynchronously { | ||||
|     DoricAsyncResult *ret = [self pureCallEntity:DORIC_ENTITY_FETCH_DIRTY_DATA withArgumentsArray:@[]]; | ||||
|     NSArray *array = [ret waitUntilResult:^(JSValue *models) { | ||||
|         return [models toArray]; | ||||
|     }]; | ||||
|     DoricShaderPlugin *shaderPlugin = self.pluginInstanceMap[@"Shader"]; | ||||
|     if (!shaderPlugin) { | ||||
|         shaderPlugin = [[DoricShaderPlugin alloc] initWithContext:self]; | ||||
|         self.pluginInstanceMap[@"Shader"] = shaderPlugin; | ||||
|     } | ||||
|     for (NSDictionary *model in array) { | ||||
|         [shaderPlugin render:model withPromise:nil]; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @end | ||||
|   | ||||
| @@ -27,4 +27,6 @@ | ||||
| @property(nonatomic, strong) void (^frameChangedBlock)(CGSize frameSize); | ||||
|  | ||||
| - (void)config:(NSString *)script alias:(NSString *)alias extra:(NSString *)extra; | ||||
|  | ||||
| - (void)renderSynchronously; | ||||
| @end | ||||
| @@ -19,6 +19,7 @@ | ||||
| 
 | ||||
| #import "DoricPanel.h" | ||||
| #import "Doric.h" | ||||
| #import "DoricConstant.h" | ||||
| 
 | ||||
| @interface DoricPanel () | ||||
| @property(nonatomic, assign) CGFloat renderedWidth; | ||||
| @@ -79,4 +80,17 @@ - (void)viewDidDisappear:(BOOL)animated { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| - (void)renderSynchronously { | ||||
|     [self.doricContext renderSynchronously]; | ||||
|     CGSize newSize = self.doricContext.rootNode.view.frame.size; | ||||
|     if (self.renderedWidth != newSize.width || self.renderedWidth != newSize.height) { | ||||
|         self.renderedWidth = newSize.width; | ||||
|         self.renderedHeight = newSize.height; | ||||
|         self.view.width = newSize.width; | ||||
|         self.view.height = newSize.height; | ||||
|         if (self.frameChangedBlock) { | ||||
|             self.frameChangedBlock(newSize); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @end | ||||
|   | ||||
| @@ -23,10 +23,6 @@ | ||||
| #import <Foundation/Foundation.h> | ||||
| #import "DoricNativePlugin.h" | ||||
|  | ||||
| NS_ASSUME_NONNULL_BEGIN | ||||
|  | ||||
| @interface DoricShaderPlugin : DoricNativePlugin | ||||
|  | ||||
| - (void)render:(NSDictionary *)argument withPromise:(DoricPromise *)promise; | ||||
| @end | ||||
|  | ||||
| NS_ASSUME_NONNULL_END | ||||
|   | ||||
| @@ -70,3 +70,5 @@ extern NSString *const DORIC_ENTITY_HIDDEN; | ||||
| extern NSString *const DORIC_ENTITY_BUILD; | ||||
|  | ||||
| extern NSString *const DORIC_ENTITY_ENV_CHANGE; | ||||
|  | ||||
| extern NSString *const DORIC_ENTITY_FETCH_DIRTY_DATA; | ||||
|   | ||||
| @@ -88,3 +88,5 @@ | ||||
| NSString *const DORIC_ENTITY_BUILD = @"__build__"; | ||||
| 
 | ||||
| NSString *const DORIC_ENTITY_ENV_CHANGE = @"__onEnvChanged__"; | ||||
| 
 | ||||
| NSString *const DORIC_ENTITY_FETCH_DIRTY_DATA = @"__fetchEffectiveData__"; | ||||
|   | ||||
| @@ -1327,6 +1327,48 @@ var Panel = /** @class */ (function () { | ||||
|             }); | ||||
|         } | ||||
|     }; | ||||
|     Panel.prototype.__fetchEffectiveData__ = function () { | ||||
|         var e_4, _a, e_5, _b; | ||||
|         var diryData = []; | ||||
|         if (this.destroyed) { | ||||
|             return diryData; | ||||
|         } | ||||
|         if (this.__root__.isDirty()) { | ||||
|             var model = this.__root__.toModel(); | ||||
|             diryData.push(JSON.parse(JSON.stringify(model))); | ||||
|             this.__root__.clean(); | ||||
|         } | ||||
|         try { | ||||
|             for (var _c = __values$3(this.headviews.values()), _d = _c.next(); !_d.done; _d = _c.next()) { | ||||
|                 var map = _d.value; | ||||
|                 try { | ||||
|                     for (var _e = (e_5 = void 0, __values$3(map.values())), _f = _e.next(); !_f.done; _f = _e.next()) { | ||||
|                         var v = _f.value; | ||||
|                         if (v.isDirty()) { | ||||
|                             var model = v.toModel(); | ||||
|                             diryData.push(JSON.parse(JSON.stringify(model))); | ||||
|                             v.clean(); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 catch (e_5_1) { e_5 = { error: e_5_1 }; } | ||||
|                 finally { | ||||
|                     try { | ||||
|                         if (_f && !_f.done && (_b = _e.return)) { _b.call(_e); } | ||||
|                     } | ||||
|                     finally { if (e_5) { throw e_5.error; } } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         catch (e_4_1) { e_4 = { error: e_4_1 }; } | ||||
|         finally { | ||||
|             try { | ||||
|                 if (_d && !_d.done && (_a = _c.return)) { _a.call(_c); } | ||||
|             } | ||||
|             finally { if (e_4) { throw e_4.error; } } | ||||
|         } | ||||
|         return diryData; | ||||
|     }; | ||||
|     Panel.prototype.onRenderFinished = function () { | ||||
|         this.onRenderFinishedCallback.forEach(function (e) { | ||||
|             e(); | ||||
|   | ||||
| @@ -1026,6 +1026,27 @@ class Panel { | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
|     __fetchEffectiveData__() { | ||||
|         const diryData = []; | ||||
|         if (this.destroyed) { | ||||
|             return diryData; | ||||
|         } | ||||
|         if (this.__root__.isDirty()) { | ||||
|             const model = this.__root__.toModel(); | ||||
|             diryData.push(JSON.parse(JSON.stringify(model))); | ||||
|             this.__root__.clean(); | ||||
|         } | ||||
|         for (let map of this.headviews.values()) { | ||||
|             for (let v of map.values()) { | ||||
|                 if (v.isDirty()) { | ||||
|                     const model = v.toModel(); | ||||
|                     diryData.push(JSON.parse(JSON.stringify(model))); | ||||
|                     v.clean(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return diryData; | ||||
|     } | ||||
|     onRenderFinished() { | ||||
|         this.onRenderFinishedCallback.forEach(e => { | ||||
|             e(); | ||||
|   | ||||
| @@ -2566,6 +2566,27 @@ class Panel { | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
|     __fetchEffectiveData__() { | ||||
|         const diryData = []; | ||||
|         if (this.destroyed) { | ||||
|             return diryData; | ||||
|         } | ||||
|         if (this.__root__.isDirty()) { | ||||
|             const model = this.__root__.toModel(); | ||||
|             diryData.push(JSON.parse(JSON.stringify(model))); | ||||
|             this.__root__.clean(); | ||||
|         } | ||||
|         for (let map of this.headviews.values()) { | ||||
|             for (let v of map.values()) { | ||||
|                 if (v.isDirty()) { | ||||
|                     const model = v.toModel(); | ||||
|                     diryData.push(JSON.parse(JSON.stringify(model))); | ||||
|                     v.clean(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return diryData; | ||||
|     } | ||||
|     onRenderFinished() { | ||||
|         this.onRenderFinishedCallback.forEach(e => { | ||||
|             e(); | ||||
|   | ||||
							
								
								
									
										1
									
								
								doric-js/index.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								doric-js/index.d.ts
									
									
									
									
										vendored
									
									
								
							| @@ -741,6 +741,7 @@ declare module "doric" { | ||||
| 		private nativeRender; | ||||
| 		private hookBeforeNativeCall; | ||||
| 		private hookAfterNativeCall; | ||||
| 		private __fetchEffectiveData__; | ||||
| 		onRenderFinished(): void; | ||||
| 		addOnRenderFinishedCallback(cb: () => void): void; | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										1
									
								
								doric-js/lib/src/ui/panel.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								doric-js/lib/src/ui/panel.d.ts
									
									
									
									
										vendored
									
									
								
							| @@ -44,6 +44,7 @@ export declare abstract class Panel { | ||||
|     private nativeRender; | ||||
|     private hookBeforeNativeCall; | ||||
|     private hookAfterNativeCall; | ||||
|     private __fetchEffectiveData__; | ||||
|     onRenderFinished(): void; | ||||
|     addOnRenderFinishedCallback(cb: () => void): void; | ||||
| } | ||||
|   | ||||
| @@ -199,6 +199,27 @@ export class Panel { | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
|     __fetchEffectiveData__() { | ||||
|         const diryData = []; | ||||
|         if (this.destroyed) { | ||||
|             return diryData; | ||||
|         } | ||||
|         if (this.__root__.isDirty()) { | ||||
|             const model = this.__root__.toModel(); | ||||
|             diryData.push(JSON.parse(JSON.stringify(model))); | ||||
|             this.__root__.clean(); | ||||
|         } | ||||
|         for (let map of this.headviews.values()) { | ||||
|             for (let v of map.values()) { | ||||
|                 if (v.isDirty()) { | ||||
|                     const model = v.toModel(); | ||||
|                     diryData.push(JSON.parse(JSON.stringify(model))); | ||||
|                     v.clean(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return diryData; | ||||
|     } | ||||
|     onRenderFinished() { | ||||
|         this.onRenderFinishedCallback.forEach(e => { | ||||
|             e(); | ||||
|   | ||||
| @@ -13,7 +13,7 @@ | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  */ | ||||
| import { View, Group } from "./view" | ||||
| import { View, Group, NativeViewModel } from "./view" | ||||
| import { loge } from '../util/log' | ||||
| import { Model } from '../util/types' | ||||
| import { Root } from '../widget/layouts' | ||||
| @@ -234,6 +234,28 @@ export abstract class Panel { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private __fetchEffectiveData__() { | ||||
|         const diryData: NativeViewModel[] = []; | ||||
|         if (this.destroyed) { | ||||
|             return diryData; | ||||
|         } | ||||
|         if (this.__root__.isDirty()) { | ||||
|             const model = this.__root__.toModel() | ||||
|             diryData.push(JSON.parse(JSON.stringify(model))); | ||||
|             this.__root__.clean(); | ||||
|         } | ||||
|         for (let map of this.headviews.values()) { | ||||
|             for (let v of map.values()) { | ||||
|                 if (v.isDirty()) { | ||||
|                     const model = v.toModel() | ||||
|                     diryData.push(JSON.parse(JSON.stringify(model))); | ||||
|                     v.clean(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return diryData; | ||||
|     } | ||||
|  | ||||
|     onRenderFinished() { | ||||
|         this.onRenderFinishedCallback.forEach(e => { | ||||
|             e() | ||||
|   | ||||
							
								
								
									
										21
									
								
								doric-web/dist/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								doric-web/dist/index.js
									
									
									
									
										vendored
									
									
								
							| @@ -2641,6 +2641,27 @@ class Panel { | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
|     __fetchEffectiveData__() { | ||||
|         const diryData = []; | ||||
|         if (this.destroyed) { | ||||
|             return diryData; | ||||
|         } | ||||
|         if (this.__root__.isDirty()) { | ||||
|             const model = this.__root__.toModel(); | ||||
|             diryData.push(JSON.parse(JSON.stringify(model))); | ||||
|             this.__root__.clean(); | ||||
|         } | ||||
|         for (let map of this.headviews.values()) { | ||||
|             for (let v of map.values()) { | ||||
|                 if (v.isDirty()) { | ||||
|                     const model = v.toModel(); | ||||
|                     diryData.push(JSON.parse(JSON.stringify(model))); | ||||
|                     v.clean(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return diryData; | ||||
|     } | ||||
|     onRenderFinished() { | ||||
|         this.onRenderFinishedCallback.forEach(e => { | ||||
|             e(); | ||||
|   | ||||
							
								
								
									
										2
									
								
								doric-web/dist/index.js.map
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								doric-web/dist/index.js.map
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
		Reference in New Issue
	
	Block a user