Skip to content
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

MVVM新增编程语言zig!实现了利用zig的泛型/反射特性直接将Model构造出View-Model #64

Open
ufbycd opened this issue Nov 10, 2024 · 6 comments

Comments

@ufbycd
Copy link

ufbycd commented Nov 10, 2024

研究了几天,确实可以实现通过zig的泛型/反射特性,直接用Model在编译时构造出View-Model:https://gitee.com/ufbycd/awtk-mvvm-zig-example

实现过程中遇到的问题:

  • zig直接调用C时暂不支持包含位域的API,后续AWTK地否考虑去除几个重要的头文件内的位域以方便zig调用?主要为这几个头文件:base/widget.htkc/object.htkc/value.h(目前已经手动适配了位域而无需修改AWTK源码,但整体来说还是有点不便的,建议不要用位域,内存对齐跑起来才快)
  • awtk_main.inc这种形式不方便zig调用,且zig要求main函数必须要在zig源码内,故awtk_main.inc文件不能直接使用,需要在zig内重新实现(还是由zig实现main函数好点,使用zig的defer延迟调用实现起来要好看很多;且在初始化代码内接收动态构建参数也很容易实现)
  • View-Model中setProp的属性类型如果是字符串的话,容易出现内存管理错误 (已解决,是我的问题,是字符串在zig和c之间转换不正确导致)
@xianjimli
Copy link
Member

好的,谢谢。我抽空研究一下。

@ufbycd
Copy link
Author

ufbycd commented Dec 2, 2024

实现v-for列表渲染时遇到问题:软件启动时可以显示列表的多个item,但启动后再添加item则不能刷新显示。
列表UI片断如下:

      <list_item v-for="{users}" w="100%" children_layout="default(rows=1,cols=0,s=0)">
        <label w="20%" style="table" v-data:text="{item.name}" />
        <label w="40%" style="table" v-data:text="{item.age}" />
        <label w="40%" style="table" v-data:text="{item.gender}"/>
      </list_item>

经测试发现:

  • 启动时会getProp名为users的object,并对此object getProp名为#size的属性作为列表的长度;
  • 但通过命令添加列表的item并返回RET_ITEMS_CHANGED后,只getProp名为users的object,没有去getProp此object的#size的属性,导致列表没有刷新

这里最好应该通过整型属性users.#size来确定列表长度而非要求用户返回一个对象,导致我要在model_list数据结构里专门搞一个只包含#size属性的对象来响应这个getProp请求。

@ufbycd
Copy link
Author

ufbycd commented Dec 7, 2024

将awtk-mvvm按以下补丁修改后上述问题就解决了,并修复了之前一个view-model不支持两个表格的问题(#62):

diff --git a/src/mvvm/awtk/binding_context_awtk.c b/src/mvvm/awtk/binding_context_awtk.c
index c6d6378..03bfe77 100644
--- a/src/mvvm/awtk/binding_context_awtk.c
+++ b/src/mvvm/awtk/binding_context_awtk.c
@@ -540,8 +540,13 @@
       return TK_OBJECT(view_model) - target;
     } else {
       if (view_model_get_prop(view_model, path, &v) == RET_OK) {
-        tk_object_t* obj = value_object(&v);
-        return obj - target;
+        if (v.type == VALUE_TYPE_OBJECT) {
+          tk_object_t* obj = value_object(&v);
+          return obj - target;
+        }
+
+        items_binding_t* binding = ITEMS_BINDING(rule);
+        return (value_uint32(&v) != binding->items_count) ? 0 : -1;
       }
     }
   }
diff --git a/src/mvvm/awtk/ui_loader_mvvm.c b/src/mvvm/awtk/ui_loader_mvvm.c
index cd061a0..2ce62cc 100644
--- a/src/mvvm/awtk/ui_loader_mvvm.c
+++ b/src/mvvm/awtk/ui_loader_mvvm.c
@@ -756,16 +756,24 @@
     tk_object_t* obj = NULL;
     const char* items_name = binding->items_name;
     const char* items_length_name = TK_OBJECT_PROP_SIZE;
+    uint32_t new_count = 0;
 
     if (binding_context_get_prop_by_rule(ctx, rule, items_name, &v) == RET_OK) {
-      obj = value_object(&v);
+      if (v.type == VALUE_TYPE_OBJECT) {
+        obj = value_object(&v);
+        if (obj == TK_OBJECT(view_model) && tk_object_is_collection(obj)) {
+          items_length_name = VIEW_MODEL_PROP_ITEMS;
+        }
+
+        if (obj != NULL) {
+          new_count = tk_object_get_prop_uint32(obj, items_length_name, 0);
+        }
+      } else {
+        new_count = value_uint32(&v);
+      }
     }
 
-    if (obj == TK_OBJECT(view_model) && tk_object_is_collection(obj)) {
-      items_length_name = VIEW_MODEL_PROP_ITEMS;
-    }
-
-    if (obj == NULL) {
+    if (new_count == 0) {
       widget_t* widget = NULL;
       uint32_t old_count = binding->items_count;
 
@@ -787,7 +795,6 @@
       uint32_t i = 0;
       widget_t* widget = NULL;
       uint32_t first_index = binding_context_calc_widget_index_of_rule(ctx, rule);
-      uint32_t new_count = tk_object_get_prop_uint32(obj, items_length_name, 0);
       uint32_t old_count = binding->items_count;
       const char* id_name = binding->id_name;
       value_t* pid = NULL;

修改后效果如下:
屏幕截图_20241207_093246
表格UI如下:

  <list_view x="c" y="230" w="90%" h="240" item_height="40">
    <row x="0" y="0" w="100%" h="40" children_layout="default(rows=1,cols=0,s=0)">
      <label w="20%" style="table_title" tr_text="姓名" />
      <label w="40%" style="table_title" tr_text="年龄" />
      <label w="40%" style="table_title" tr_text="性别" />
    </row>

    <scroll_view x="0" y="40" w="100%" h="-40">
      <list_item v-for="{males}" w="100%" children_layout="default(rows=1,cols=0,s=0)">
        <label w="20%" style="table" v-data:text="{item.name}" />
        <label w="40%" style="table" v-data:text="{item.age}" />
        <label w="40%" style="table" v-data:text="{item.gender}"/>
      </list_item>
    </scroll_view>
    <scroll_bar_m x="right" y="40" w="6" h="-40" value="0" />
  </list_view>

  <list_view x="c" y="480" w="90%" h="200" item_height="40">
    <scroll_view x="0" y="0" w="100%" h="100%">
      <list_item v-for="{females}" w="100%" children_layout="default(rows=1,cols=0,s=0)">
        <label w="20%" style="table" v-data:text="{item.name}" />
        <label w="40%" style="table" v-data:text="{item.age}" />
        <label w="40%" style="table" v-data:text="{item.gender}"/>
      </list_item>
    </scroll_view>
    <scroll_bar_m x="right" y="0" w="6" h="100%" value="0" />
  </list_view>

@xuchaoze
Copy link
Collaborator

View-Model中setProp的属性类型如果是字符串的话,容易出现内存管理错误,这个现象怎么出现的

@ufbycd
Copy link
Author

ufbycd commented Dec 13, 2024

View-Model中setProp的属性类型如果是字符串的话,容易出现内存管理错误,这个现象怎么出现的

今天再次测试,发现没有问题了。可能是我之前将字符串在Zig和C之间转换不正确导致的。

@ufbycd
Copy link
Author

ufbycd commented Dec 14, 2024

目前已经手动适配了位域而无需修改AWTK源码,但整体来说还是有点不便的,需要分析并手动导入所有相关的API,参见此文件。建议不要用位域,内存对齐跑起来才快。
AWTK目前的问题是在算力较小的MPU芯片上性能不太好,位域省不了多少内存,但对运行效率影响较大。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants