获取最近访问列表场景

为了快速访问最近使用的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标记为共享模块
    'use shared'
    
    // SendableClass实例对象在不同线程间可共享
    @Sendable
    class SendableClass {
      // 使用SendableLruCache实例对象时需加锁,避免多线程同时操作导致数据不一致
      private lock_: ArkTSUtils.locks.AsyncLock = new ArkTSUtils.locks.AsyncLock();
      private 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
    @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)
            .position({ x: '50%' })
            .onClick(() => {
              this.getUIContext().getRouter().pushUrl({ url: 'pages/GetRecentList' });
            })
        }
        .height('100%')
        .width('100%')
      }
    }
    
    // Book2.ets
    @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)
            .position({ x: '50%' })
            .onClick(() => {
              this.getUIContext().getRouter().pushUrl({ url: 'pages/GetRecentList' });
            })
        }
        .height('100%')
        .width('100%')
      }
    }
    
    // Book3.ets
    @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)
            .position({ x: '50%' })
            .onClick(() => {
              this.getUIContext().getRouter().pushUrl({ url: 'pages/GetRecentList' });
            })
        }
        .height('100%')
        .width('100%')
      }
    }
    
    // Book4.ets
    @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)
            .position({ x: '50%' })
            .onClick(() => {
              this.getUIContext().getRouter().pushUrl({ url: 'pages/GetRecentList' });
            })
        }
        .height('100%')
        .width('100%')
      }
    }
    
    // main_pages.json
    
    {
      "src": [
        "pages/Index",
        "pages/Book1",
        "pages/Book2",
        "pages/Book3",
        "pages/Book4",
        "pages/GetRecentList"
      ]
    }
    
  3. 访问书架页面时,自动展示最近访问的图书列表。

    // GetRecentList.ets
    import { taskpool } from '@kit.ArkTS';
    import { lruCache } from '../utils/LruCache'
    // ...
    
    @Concurrent
    async function updateBooks(key: string, value: string) {
      // 在子线程更新最近访问列表
      await lruCache.put(key, value);
    }
    
    @Entry
    @Component
    struct GetRecentList {
      @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);
              this.getUIContext().getRouter().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);
              this.getUIContext().getRouter().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);
              this.getUIContext().getRouter().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);
              this.getUIContext().getRouter().pushUrl({ url: 'pages/' + value });
            })
          // ...
        }
        .height('100%')
        .width('100%')
      }
    }