1# Obtaining the Recently Accessed List 2 3To quickly access the recently used [Sendable](arkts-sendable.md) objects, ArkTS introduces [SendableLruCache](../reference/apis-arkts/js-apis-arkts-utils.md#sendablelrucachek-v18) since API version 18. With this class, you can add, delete, and obtain Sendable objects from a SendableLruCache instance to quickly access the recently used Sendable objects. This topic describes how to use SendableLruCache to obtain the recently accessed list. It uses a bookshelf as an example. Every time a user opens a book, the book information is updated to the recently accessed list. When the user accesses the bookshelf next time, the list of books that the user has looked at is displayed. 4 5> **NOTE** 6> 7> SendableLruCache instances must be locked to prevent data inconsistency caused by concurrent operations from multiple threads. 8> 9> Only Sendable objects can be put into a SendableLruCache instance. 10 111. Create a SendableLruCache instance and set its maximum capacity based on service requirements. 12 13 In this example, the maximum capacity of the SendableLruCache instance is set to 4, the Sendable class is used for management, and the Sendable class instance is exported. 14 15 ```ts 16 // LruCache.ets 17 18 import { ArkTSUtils } from '@kit.ArkTS'; 19 20 // Use the 'use shared' marker to mark a module shareable. 21 "use shared" 22 23 // The SendableClass instance can be shared across different threads. 24 @Sendable 25 class SendableClass { 26 // Lock the SendableLruCache instances to prevent data inconsistency caused by concurrent operations from multiple threads. 27 lock_: ArkTSUtils.locks.AsyncLock = new ArkTSUtils.locks.AsyncLock(); 28 books_: ArkTSUtils.SendableLruCache<string, string> = new ArkTSUtils.SendableLruCache<string, string>(4); 29 30 constructor() { 31 this.books_.put("fourth", "Book4"); 32 this.books_.put("third", "Book3"); 33 this.books_.put("second", "Book2"); 34 this.books_.put("first", "Book1"); 35 } 36 37 // Wrap the put, get, and keys methods and perform the lock operation. 38 public async put(key: string, value: string) { 39 await this.lock_.lockAsync(() => { 40 this.books_.put(key, value); 41 }) 42 } 43 44 public async get(key: string): Promise<string | undefined> { 45 return this.lock_.lockAsync(() => { 46 return this.books_.get(key); 47 }); 48 } 49 50 public async keys(): Promise<string[]> { 51 return this.lock_.lockAsync(() => { 52 return this.books_.keys(); 53 }); 54 } 55 } 56 57 export let lruCache = new SendableClass(); 58 ``` 59 602. In the same directory as the **Index.ets** page, create four book pages. Each page shows its own book information. Register the path of each page in the **main_pages.json** file under **src/main/resources/base/profile/**. 61 62 ```ts 63 // Book1.ets 64 65 @Entry 66 @Component 67 struct Index1 { 68 @State message: string = 'Hello World!'; 69 70 build() { 71 RelativeContainer() { 72 Text("Content of book 1") 73 .id('first book') 74 .fontSize(20) 75 .padding(10) 76 .fontWeight(FontWeight.Bold) 77 .alignRules({ 78 center: { anchor: 'container', align: VerticalAlign.Center }, 79 middle: { anchor: 'container', align: HorizontalAlign.Center } 80 }) 81 Button('Back') 82 .fontSize(20) 83 .padding(10) 84 .fontWeight(FontWeight.Bold) 85 .onClick(() => { 86 this.getUIContext().getRouter().pushUrl({ url: 'pages/Index' }); 87 }) 88 } 89 .height('100%') 90 .width('100%') 91 } 92 } 93 ``` 94 ```ts 95 // Book2.ets 96 97 @Entry 98 @Component 99 struct Index2 { 100 @State message: string = 'Hello World!'; 101 102 build() { 103 RelativeContainer() { 104 Text("Content of book 2") 105 .id('second book') 106 .fontSize(20) 107 .padding(10) 108 .fontWeight(FontWeight.Bold) 109 .alignRules({ 110 center: { anchor: 'container', align: VerticalAlign.Center }, 111 middle: { anchor: 'container', align: HorizontalAlign.Center } 112 }) 113 Button('Back') 114 .fontSize(20) 115 .padding(10) 116 .fontWeight(FontWeight.Bold) 117 .onClick(() => { 118 this.getUIContext().getRouter().pushUrl({ url: 'pages/Index' }); 119 }) 120 } 121 .height('100%') 122 .width('100%') 123 } 124 } 125 ``` 126 ```ts 127 // Book3.ets 128 129 @Entry 130 @Component 131 struct Index3 { 132 @State message: string = 'Hello World!'; 133 134 build() { 135 RelativeContainer() { 136 Text("Content of book 3") 137 .id('third book') 138 .fontSize(20) 139 .padding(10) 140 .fontWeight(FontWeight.Bold) 141 .alignRules({ 142 center: { anchor: 'container', align: VerticalAlign.Center }, 143 middle: { anchor: 'container', align: HorizontalAlign.Center } 144 }) 145 Button('Back') 146 .fontSize(20) 147 .padding(10) 148 .fontWeight(FontWeight.Bold) 149 .onClick(() => { 150 this.getUIContext().getRouter().pushUrl({ url: 'pages/Index' }); 151 }) 152 } 153 .height('100%') 154 .width('100%') 155 } 156 } 157 ``` 158 ```ts 159 // Book4.ets 160 161 @Entry 162 @Component 163 struct Index4 { 164 @State message: string = 'Hello World!'; 165 166 build() { 167 RelativeContainer() { 168 Text("Content of book 4") 169 .id('fourth book') 170 .fontSize(20) 171 .padding(10) 172 .fontWeight(FontWeight.Bold) 173 .alignRules({ 174 center: { anchor: 'container', align: VerticalAlign.Center }, 175 middle: { anchor: 'container', align: HorizontalAlign.Center } 176 }) 177 Button('Back') 178 .fontSize(20) 179 .padding(10) 180 .fontWeight(FontWeight.Bold) 181 .onClick(() => { 182 this.getUIContext().getRouter().pushUrl({ url: 'pages/Index' }); 183 }) 184 } 185 .height('100%') 186 .width('100%') 187 } 188 } 189 ``` 190 ```json 191 // main_pages.json 192 193 { 194 "src": [ 195 "pages/Index", 196 "pages/Book1", 197 "pages/Book2", 198 "pages/Book3", 199 "pages/Book4" 200 ] 201 } 202 ``` 203 2043. Each time a user accesses the bookshelf page, the application displays the list of recently accessed books. 205 206 ```ts 207 // Index.ets 208 209 import { taskpool } from '@kit.ArkTS'; 210 import { lruCache } from './LruCache' 211 212 @Concurrent 213 async function updateBooks(key: string, value: string) { 214 // Update the latest access list in the child thread. 215 await lruCache.put(key, value); 216 } 217 218 @Entry 219 @Component 220 struct Index { 221 @State message: string = 'Bookshelf' 222 @State books: string[] = []; 223 224 async aboutToAppear () { 225 // The application automatically obtains the list of recently accessed books. 226 this.books = await lruCache.keys(); 227 } 228 229 build() { 230 Column({ space: 1 }) { 231 Text(this.message) 232 .id('HelloWorld') 233 .fontSize(50) 234 .fontWeight(FontWeight.Bold) 235 .alignRules({ 236 center: { anchor: 'container', align: VerticalAlign.Center }, 237 middle: { anchor: 'container', align: HorizontalAlign.Center } 238 }) 239 Button(this.books[3]) 240 .fontSize(20) 241 .padding(10) 242 .fontWeight(FontWeight.Bold) 243 .onClick(async () => { 244 // Obtain the bound book information. 245 let value = await lruCache.get(this.books[3]); 246 // Update the recently accessed list. 247 taskpool.execute(updateBooks, this.books[3], value); 248 this.getUIContext().getRouter().pushUrl({ url: 'pages/' + value }); 249 }) 250 Button(this.books[2]) 251 .fontSize(20) 252 .padding(10) 253 .fontWeight(FontWeight.Bold) 254 .onClick(async () => { 255 // Obtain the bound book information. 256 let value = await lruCache.get(this.books[2]); 257 // Update the recently accessed list. 258 taskpool.execute(updateBooks, this.books[2], value); 259 this.getUIContext().getRouter().pushUrl({ url: 'pages/' + value }); 260 }) 261 Button(this.books[1]) 262 .fontSize(20) 263 .padding(10) 264 .fontWeight(FontWeight.Bold) 265 .onClick(async () => { 266 // Obtain the bound book information. 267 let value = await lruCache.get(this.books[1]); 268 // Update the recently accessed list. 269 taskpool.execute(updateBooks, this.books[1], value); 270 this.getUIContext().getRouter().pushUrl({ url: 'pages/' + value }); 271 }) 272 Button(this.books[0]) 273 .fontSize(20) 274 .padding(10) 275 .fontWeight(FontWeight.Bold) 276 .onClick(async () => { 277 // Obtain the bound book information. 278 let value = await lruCache.get(this.books[0]); 279 // Update the recently accessed list. 280 taskpool.execute(updateBooks, this.books[0], value); 281 this.getUIContext().getRouter().pushUrl({ url: 'pages/' + value }); 282 }) 283 } 284 .height('100%') 285 .width('100%') 286 } 287 } 288 ``` 289