Use PAGImageView
Introduction
Starting from version PAG 4.2, a dedicated play component PAGImageView for UI scenarios has been introduced. This component can effectively bypass the disadvantages of the PAGView GPU real-time rendering solution in UI scenarios. It is particularly useful when multiple PAG files are played simultaneously in a UI list or on the same page. By leveraging disk caching, it significantly reduces memory usage and enhances rendering performance. The core principle behind PAGImageView is to cache rendering data locally while rendering the current frame of an animation file. As a result, users only experience a short-lived GPU-based real-time rendering image throughout the animation's lifecycle. Subsequently, the presentation directly accesses the high-speed disk cache, which remains valid even after restarting the app. This approach minimizes the additional overhead associated with GPU real-time rendering, resulting in improved overall rendering efficiency. Furthermore, since there is no GPU bridging layer between PAGImageView and the UI framework, it seamlessly enables high-performance mixing without requiring any additional merge play logic.
Applicable Scenarios
The implementation principle of PAGImageView is to compress and cache the rendered content of each frame to the local disk through LZ4. If the PAGImageView renders at a larger size and the PAG file duration is longer, such as in the case of a full screen on a mobile phone, it will occupy a large amount of disk space for caching, and it may take several hundred MB to cache a PAG file. Currently, the maximum disk space occupied by the disk cache is 1GB by default. If there are many such cases, the cache clearing logic will be triggered constantly, which will not improve the performance but will make it worse.
PAGImageView is ideal for scenarios with UI lists or multiple small-scale views on a page. In this scenario, the rendered size is relatively small, and a PAG file takes up only tens of MBs of disk space after being cached. When rendering, it continuously hits the cache, thereby improving performance. We still recommend using PAGView for other scenarios.
Moreover, in certain cases where image sequences like WebP and APNG are employed, due to the relatively small file size and the number of frames, the content of the image sequence is generally fully cached in memory. This allows for direct retrieval from the memory cache during the rendering process, resulting in minimal CPU usage. To address this scenario, PAGImageView offers a comprehensive memory cache mode. While this mode increases memory usage, it significantly reduces CPU load.
Specific Usage
Used in Normal View
Android
This example of MultiplePAGImageViewActivity demonstrates the usage scenario as a normal view in xml.
Declared it in xml like a normal view
<org.libpag.PAGImageView
android:id="@+id/pagView1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
Set the corresponding parameters for PAGImageView in the code
void fireImageView(int id, String path) {
// Find View from xml
PAGImageView view = findViewById(id);
// Like PAGView, set the PAG file path to accept two paths from assets and sdcard
view.setPath(path);
// Set the number of loops for the animation, with -1 being an infinite loop
view.setRepeatCount(-1);
// Play the animation
view.play();
}
iOS
PAGImageView* pagImageView = [[PAGImageView alloc] initWithFrame:CGRectMake(x, y, w, h)];
[pagImageView setPath:[[NSBundle mainBundle] pathForResource:pagPath];
[pagImageView setCacheAllFramesInMemory:NO];
[pagImageView setRepeatCount:-1];
[pagImageView play];
Used in ListView
Android
This example of PAGImageViewListActivity demonstrates the usage scenario in ListView/GridView
Declare it like a normal view in the item list
<org.libpag.PAGImageView
android:id="@+id/pagView"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
Initialize and play view in RecyclerView.Adapter
@Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
viewHolder.getView().setPath(mDataSet[position]);
viewHolder.getView().setRepeatCount(-1);
viewHolder.getView().play();
}
iOS
#define WIDTH 100
@interface PAGCell : UITableViewCell
@property (nonatomic,strong) PAGImageView* pagImageView;
@property (nonatomic,strong) NSString* filePath;
@end
@implementation PAGCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
self.pagImageView = [[PAGImageView alloc] initWithFrame:CGRectMake(20, 0, WIDTH, WIDTH)];
[self.contentView addSubview:self.pagImageView];
}
return self;
}
- (void)setFilePath:(NSString *)filePath {
if ([filePath length] > 0) {
[self.pagImageView setPath:filePath];
[self.pagImageView setCacheAllFramesInMemory:NO];
[self.pagImageView setRepeatCount:-1];
[self.pagImageView play];
}
}
@end
Other Configurations
memoryCache
By default, PAGImageView enables disk caching, recognizing its value for efficient data retrieval. However, memory caching is still disabled by default due to memory constraints. If necessary, you can activate it by invoking the corresponding API.
// Android
public void setCacheAllFramesInMemory(boolean enable);
// iOS
- (void)setCacheAllFramesInMemory:(BOOL)enable;
This interface will significantly increase the memory usage. When using it, you should evaluate whether it is suitable for the specific scenario.
renderScale
To optimize performance for low-end models that don't require high-definition rendering, it's recommended to consider adjusting the renderScale setting. This will help reduce both CPU and memory usage.
When rendering or caching, the output size is scaled by this ratio. For instance, if the original size is 100 * 100 and the renderScale is set to 0.5, the resulting size will be 50 * 50.
// Android
public void setRenderScale(float renderScale);
// iOS
- (void)setRenderScale:(float)scale;
maxDisk
For files cached to disk, they may gradually increase. To solve this problem, we have added an interface for setting maxDisk.
// Android
public static void SetMaxDiskSize(long size);
PAGDiskCache.java
// iOS
+ (void)SetMaxDiskSize:(size_t)size;
PAGDiskCache.h
Resource Settings
We have two ways of setting resources: setPath and setComposition.
If there is no need to modify the original PAG file here, we strongly recommend using setPath to input data.
By using the setPath method to set resources, we only need GPU and PAG related resources during the first draw and will release them immediately after use. This situation can lead to significant memory optimization.
When setting resources through setComposition, the PAGComposition object is not directly generated through PAFile. load, or there are modifications to the PAGComposition object. When PAGImageView detaches, we will automatically clean up the disk cache.