DEV Community

Cover image for HarmonyOS Development: How to Update Object Arrays
程序员一鸣
程序员一鸣

Posted on

HarmonyOS Development: How to Update Object Arrays

introduction

Based on Api13

Before their own package a list refresh library, has been running for a long time, but recently received a problem, said to be in the list of a certain data update, found that the data has not changed, received the problem immediately into the investigation, and finally found that the use is not in accordance with the specification implementation, this problem is common in the development of object array update problems, simply a simple record.

We know that for a basic type of array, we can directly change, you can affect the data changes, such as the following case, a simple array load, using the @State decorator, after clicking the button, you can find that the array index 0 data has changed.

  @Entry
  @Component
  struct Index {
    @State items: string[] = ["条目一","条目二","条目三"]

    build() {
      Column() {
        ForEach(this.items, (item: string) => {
          Text(item)
            .height(30)
        })
        Button("修改数据")
          .onClick(() => {
            this.items[0] = "这是条目一修改后的数据"
          })
      }.width("100%")
        .alignItems(HorizontalAlign.Center)
    }
  }
Enter fullscreen mode Exit fullscreen mode

In the same example above, we change the array of primitive types to an array of objects, as shown in the following code, and we can see that the data does not change after clicking the button.

class TestBean {
  name?: string

  constructor(name: string) {
    this.name = name
  }
}

@Entry
@Component
struct Index {
  @State items: TestBean[] = [
    new TestBean("条目一"),
    new TestBean("条目二"),
    new TestBean("条目三")]

  build() {
    Column() {
      ForEach(this.items, (item: TestBean) => {
        Text(item.name)
          .height(30)
      })
      Button("修改数据")
        .onClick(() => {
          this.items[0].name = "这是条目一修改后的数据"
        })
    }.width("100%")
    .alignItems(HorizontalAlign.Center)
  }
}
Enter fullscreen mode Exit fullscreen mode

Object form is the most common way in development, and updates to data are also common, such as the selected state in the entry, although the above code does not use list components such as List, but similar, there is a typical problem, that is, why basic arrays can be updated, but object arrays can not be updated?

This is because the @State decorator can only observe changes in the first layer, and changes in the second layer are not observed. If you want to update the object, you need to use the @Observed/@ObjectLink decorator.

If I don't use the @Observed/@ObjectLink decorator, can't I update? Here to do a rhetorical question, after we focus on overview, we still follow the traditional way, using decorators, see how to update the object array.

@Observed/@ObjectLink Usage

First, add the @Observed decorator to the object

@Observed
class TestBean {
  name?: string

  constructor(name: string) {
    this.name = name
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 2: View extraction subassembly

@Component
struct TextView {
  @ObjectLink item: TestBean

  build() {
    Text(this.item.name)
      .height(30)
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 3, change to subassembly

@Entry
@Component
struct Index {
  @State items: TestBean[] = [
    new TestBean("条目一"),
    new TestBean("条目二"),
    new TestBean("条目三")]

  build() {
    Column() {
      ForEach(this.items, (item: TestBean) => {
        TextView({ item: item })
      })
      Button("修改数据")
        .onClick(() => {
          this.items[0].name = "这是条目一修改后的数据"
        })
    }.width("100%")
    .alignItems(HorizontalAlign.Center)
  }
}
Enter fullscreen mode Exit fullscreen mode

After the above steps, we click the next button again and we can find that the data in the object array has changed:

Image description

@Observed/@ObjectLink is used in combination, mainly for observation of nested scenes. It is to make up for the ability limitation that decorators can only observe one layer. However, we can find that in order to update object data, we need to disassemble subcomponents and observe objects. I am just a simple component. I don't want to be so troublesome. Can I update object data? Obviously, yes.

array update

1, the entire object assignment

For an object with a simple element, we can get an array and update it directly against the corresponding index. The code is as follows: Let the new object be assigned to the specified index.

class TestBean {
  name?: string

  constructor(name: string) {
    this.name = name
  }
}

@Entry
@Component
struct Index {
  @State items: TestBean[] = [
    new TestBean("条目一"),
    new TestBean("条目二"),
    new TestBean("条目三")]

  build() {
    Column() {
      ForEach(this.items, (item: TestBean) => {
        Text(item.name)
          .height(30)
      })
      Button("修改数据")
        .onClick(() => {
          this.items[0] = new TestBean("这是条目一修改后的数据")
        })
    }.width("100%")
    .alignItems(HorizontalAlign.Center)
  }
}
Enter fullscreen mode Exit fullscreen mode

After we run, we can find that the data has also changed, the advantages of this method update are also obvious, the time complexity is low (O(1)), the code is simple and intuitive, more in line with our conventional thinking, the disadvantages are also obvious, if the object elements are more, the management is a little troublesome, after all, it is for the entire object update, not a single element of the object.

2. Single attribute assignment

In the first way, although the data update of the object array is realized, it is aimed at the whole object, not a certain attribute of a single object. This is very inconvenient for the scene of single attribute update. Some students may have thought that we can first obtain an object with a certain index, modify a certain attribute, and assign it again. Well, that sounds fine. Let's check it out:

let bean = this.items[0]
bean.name = "这是条目一修改后的数据"
this.items[0] = bean
Enter fullscreen mode Exit fullscreen mode

The above code, after we run, we can find that it does not take effect, because the object is still the original object, its reference address has not changed, in order to make it updated, we can perform the deletion and then add way, that is, first delete the data at this position, and then insert a piece of data at the same position, which realizes the dynamic change of the data. In fact, in the array, we have provided a method, that is, the splice method.

The splice method is a built-in function of the array object, mainly used to modify the contents of the array, it can be implemented,insert elements: you can insert one or more elements into the array at the specified position; you can also delete elements: you can delete one or more elements at the specified position; you can also replace elements: you can delete elements at the specified position and insert one or more new elements.

 splice(start: number, deleteCount: number, ...items: T[]): T[];
Enter fullscreen mode Exit fullscreen mode

start: Indicates the starting index position to modify (counting from 0).

deleteCount: Indicates the number of elements to delete. If 0, no elements will be deleted.

... items: T: The element to insert into the array.

We use thesplice method to optimize the above code, or in the above case, we update the data with element 0:

let bean = this.items[0]
bean.name = "这是条目一修改后的数据"
this.items.splice(0, 1, bean)
Enter fullscreen mode Exit fullscreen mode

After running, you can see that the data in the object array has changed.

relevant summary

As for the data update in the object array, three methods are exemplified at present, one is the traditional decorator method, and the other two are the operation for the data source. The data source is directly assigned, which is suitable for simple and high-frequency single-element modification. The performance is optimal and the type is safe. Thesplice method is suitable for complex operations or scenes where reference stability needs to be maintained, but performance loss should be paid attention to. In actual development, you can choose your own suitable method according to requirements.

Top comments (0)