Add API for synchronous rendering to Panel

This commit is contained in:
pengfei.zhou 2023-02-15 16:31:28 +08:00 committed by osborn
parent fc4628dde9
commit 37e93273b8
19 changed files with 269 additions and 10 deletions

View File

@ -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();
}
}
}

View File

@ -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();
}
}
});
}
});

View File

@ -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__";
}

View File

@ -73,6 +73,10 @@ NS_ASSUME_NONNULL_BEGIN
- (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

View File

@ -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

View File

@ -27,4 +27,6 @@
@property(nonatomic, strong) void (^frameChangedBlock)(CGSize frameSize);
- (void)config:(NSString *)script alias:(NSString *)alias extra:(NSString *)extra;
- (void)renderSynchronously;
@end

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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__";

View File

@ -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();

View File

@ -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();

View File

@ -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
View File

@ -741,6 +741,7 @@ declare module "doric" {
private nativeRender;
private hookBeforeNativeCall;
private hookAfterNativeCall;
private __fetchEffectiveData__;
onRenderFinished(): void;
addOnRenderFinishedCallback(cb: () => void): void;
}

View File

@ -44,6 +44,7 @@ export declare abstract class Panel {
private nativeRender;
private hookBeforeNativeCall;
private hookAfterNativeCall;
private __fetchEffectiveData__;
onRenderFinished(): void;
addOnRenderFinishedCallback(cb: () => void): void;
}

View File

@ -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();

View File

@ -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()

View File

@ -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();

File diff suppressed because one or more lines are too long