获取最近访问列表

为了快速访问最近使用的Sendable对象,从API version 18开始,ArkTS引入了SendableLruCache,用户可以通过向SendableLruCache实例对象中添加、删除、获取Sendable对象,来实现快速访问最近使用的Sendable对象。此处提供使用SendableLruCache实现获取最近使用列表的开发指导,以书架为例,用户每次打开一本图书后,需要将图书的信息更新到图书的最近访问列表中,并在下次访问书架页面时显示最近访问的图书列表。

说明:

SendableLruCache实例对象的使用需要加锁,避免多线程同时操作导致数据不一致。 存放到SendableLruCache实例中的对象必须是Sendable对象。

  1. 创建SendableLruCache实例对象,并按业务情况预设最大容量。
    此例设置SendableLruCache实例的最大容量为4,用SendableClass类来管理,并导出SendableClass类实例对象。

    // LruCache.ets
    
    import { ArkTSUtils } from '@kit.ArkTS';
    
    // 使用use shared标记为共享模块,使SendableClass实例对象在不同线程间可共享。
    "use shared"
    
    @Sendable
    class SendableClass {
      // SendableLruCache实例对象的使用需要加锁,避免多线程同时操作导致数据不一致。
      lock_: ArkTSUtils.locks.AsyncLock = new ArkTSUtils.locks.AsyncLock();
      books_: ArkTSUtils.SendableLruCache<string, string> = new ArkTSUtils.SendableLruCache<string, string>(4);
    
      constructor() {
        this.books_.put("fourth", "Book4");
        this.books_.put("third", "Book3");
        this.books_.put("second", "Book2");
        this.books_.put("first", "Book1");
      }
    
      // 封装put、get、keys方法,加锁操作。
      public async put(key: string, value: string) {
        await this.lock_.lockAsync(() => {
          this.books_.put(key, value);
        })
      }
    
      public async get(key: string): Promise<string | undefined> {
        return this.lock_.lockAsync(() => {
          return this.books_.get(key);
        });
      }
    
      public async keys(): Promise<string[]> {
        return this.lock_.lockAsync(() => {
          return this.books_.keys();
        });
      }
    }
    
    export let lruCache = new SendableClass();
    
  2. 在Index.ets页面同目录下创建4个图书页面,每个页面显示各自的图书信息,并将每个页面的路径注册到src/main/resources/base/profile/main_pages.json文件中。

    // Book1.ets
    
    import { router } from '@kit.ArkUI';
    
    @Entry
    @Component
    struct Index1 {
      @State message: string = 'Hello World!';
    
      build() {
        RelativeContainer() {
          Text("第一本书的内容")
            .id('first book')
            .fontSize(20)
            .padding(10)
            .fontWeight(FontWeight.Bold)
            .alignRules({
              center: { anchor: 'container', align: VerticalAlign.Center },
              middle: { anchor: 'container', align: HorizontalAlign.Center }
            })
          Button("返回")
            .fontSize(20)
            .padding(10)
            .fontWeight(FontWeight.Bold)
            .onClick(() => {
              router.pushUrl({
                url: 'pages/Index',
              });
            })
        }
        .height('100%')
        .width('100%')
      }
    }
    
    // Book2.ets
    
    import { router } from '@kit.ArkUI';
    
    @Entry
    @Component
    struct Index2 {
      @State message: string = 'Hello World!';
    
      build() {
        RelativeContainer() {
          Text("第二本书的内容")
            .id('second book')
            .fontSize(20)
            .padding(10)
            .fontWeight(FontWeight.Bold)
            .alignRules({
              center: { anchor: 'container', align: VerticalAlign.Center },
              middle: { anchor: 'container', align: HorizontalAlign.Center }
            })
          Button("返回")
            .fontSize(20)
            .padding(10)
            .fontWeight(FontWeight.Bold)
            .onClick(() => {
              router.pushUrl({
                url: 'pages/Index',
              });
            })
        }
        .height('100%')
        .width('100%')
      }
    }
    
    // Book3.ets
    
    import { router } from '@kit.ArkUI';
    
    @Entry
    @Component
    struct Index3 {
      @State message: string = 'Hello World!';
    
      build() {
        RelativeContainer() {
          Text("第三本书的内容")
            .id('third book')
            .fontSize(20)
            .padding(10)
            .fontWeight(FontWeight.Bold)
            .alignRules({
              center: { anchor: 'container', align: VerticalAlign.Center },
              middle: { anchor: 'container', align: HorizontalAlign.Center }
            })
          Button("返回")
            .fontSize(20)
            .padding(10)
            .fontWeight(FontWeight.Bold)
            .onClick(() => {
              router.pushUrl({
                url: 'pages/Index',
              });
            })
        }
        .height('100%')
        .width('100%')
      }
    }
    
    // Book4.ets
    
    import { router } from '@kit.ArkUI';
    
    @Entry
    @Component
    struct Index4 {
      @State message: string = 'Hello World!';
    
      build() {
        RelativeContainer() {
          Text("第四本书的内容")
            .id('fourth book')
            .fontSize(20)
            .padding(10)
            .fontWeight(FontWeight.Bold)
            .alignRules({
              center: { anchor: 'container', align: VerticalAlign.Center },
              middle: { anchor: 'container', align: HorizontalAlign.Center }
            })
          Button("返回")
            .fontSize(20)
            .padding(10)
            .fontWeight(FontWeight.Bold)
            .onClick(() => {
              router.pushUrl({
                url: 'pages/Index',
              });
            })
        }
        .height('100%')
        .width('100%')
      }
    }
    
    // main_pages.json
    
    {
      "src": [
        "pages/Index",
        "pages/Book1",
        "pages/Book2",
        "pages/Book3",
        "pages/Book4"
      ]
    }
    
  3. 每次访问书架页面时,自动获取最近访问的图书列表并展示。

    // Index.ets
    
    import { taskpool } from '@kit.ArkTS';
    import { router } from '@kit.ArkUI';
    import { lruCache } from './LruCache'
    
    @Concurrent
    async function updateBooks(key: string, value: string) {
      // 在子线程更新最近访问列表
      await lruCache.put(key, value);
    }
    
    @Entry
    @Component
    struct Index {
      @State message: string = '书架';
      @State books: string[] = [];
    
      async aboutToAppear () {
        // 自动获取最近访问的图书列表
        this.books = await lruCache.keys();
      }
    
      build() {
        Column({ space: 1 }) {
          Text(this.message)
            .id('HelloWorld')
            .fontSize(50)
            .fontWeight(FontWeight.Bold)
            .alignRules({
              center: { anchor: 'container', align: VerticalAlign.Center },
              middle: { anchor: 'container', align: HorizontalAlign.Center }
            })
          Button(this.books[3])
            .fontSize(20)
            .padding(10)
            .fontWeight(FontWeight.Bold)
            .onClick(async () => {
              // 获取绑定的图书信息
              let value = await lruCache.get(this.books[3]);
              // 更新最近访问列表
              taskpool.execute(updateBooks, this.books[3], value);
              router.pushUrl({
                url: 'pages/' + value,
              });
            })
          Button(this.books[2])
            .fontSize(20)
            .padding(10)
            .fontWeight(FontWeight.Bold)
            .onClick(async () => {
              // 获取绑定的图书信息
              let value = await lruCache.get(this.books[2]);
              // 更新最近访问列表
              taskpool.execute(updateBooks, this.books[2], value);
              router.pushUrl({
                url: 'pages/' + value,
              });
            })
          Button(this.books[1])
            .fontSize(20)
            .padding(10)
            .fontWeight(FontWeight.Bold)
            .onClick(async () => {
              // 获取绑定的图书信息
              let value = await lruCache.get(this.books[1]);
              // 更新最近访问列表
              taskpool.execute(updateBooks, this.books[1], value);
              router.pushUrl({
                url: 'pages/' + value,
              });
            })
          Button(this.books[0])
            .fontSize(20)
            .padding(10)
            .fontWeight(FontWeight.Bold)
            .onClick(async () => {
              // 获取绑定的图书信息
              let value = await lruCache.get(this.books[0]);
              // 更新最近访问列表
              taskpool.execute(updateBooks, this.books[0], value);
              router.pushUrl({
                url: 'pages/' + value,
              });
            })
        }
        .height('100%')
        .width('100%')
      }
    }