QQ泡沫乐园 · 免费提供游戏辅助,破解软件,活动资讯,喜欢记得收藏哦!
综合软件_线报活动_游戏辅助_最新电影_最优质的的辅助分享平台

本文对AndroidH5秒开方案进行了调研(组图)

泡沫乐园 2022-05-08 02:08

本文调查了Android H5的秒开方案,分析了今日头条App的秒开方案。

本文首发于:

背景

在回家的地铁上使用自己APP的H5相关功能时,可能会因为网络原因体验不佳。用微信和今日头条App,感觉很流畅,基本秒开,然后想了解一下行业内的H5秒。打开一个计划。

问题 原因 常见解决方法 WebView 缓存相关

这可以通过以下代码实现:

WebSettings webSettings = myWebView.getSettings();webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);webSettings.setDomStorageEnabled(true);webSettings.setDatabaseEnabled(true);final String dbPath = getApplicationContext().getDir("db", Context.MODE_PRIVATE).getPath();webSettings.setDatabasePath(dbPath); webSettings.setAppCacheEnabled(true);final String cachePath = getApplicationContext().getDir("cache", Context.MODE_PRIVATE).getPath();webSettings.setAppCachePath(cachePath);webSettings.setAppCacheMaxSize(5*1024*1024);webSettings.setJavaScriptEnabled(true);

开源解决方案 今日头条解决方案

我们来看看今日头条的效果。第二次断网打开页面,秒级达到打开页面的效果:

今日头条对其平台的文​​章详情页做了很多优化,包括以下几点:

内置所需文件

WebView预创建、资源预加载

第一次创建 WebView 比第二次创建要慢得多。估计第一次创建WebView需要初始化一些静态资源,第二次创建不需要初始化,所以第二次创建耗时少很多。

使用Context包装类MutableContextWrapper传入Application,预先创建WebView对象,然后预先加载一个用java代码拼接的html,并提前解析js和css资源。当您获得预先创建的 WebView 时,将其替换为 Activity 的上下文。

public class PreloadWebView {    private PreloadWebView(){}    private static final int CACHED_WEBVIEW_MAX_NUM = 2;    private static final Stack mCachedWebViewStack = new Stack<>();    public static PreloadWebView getInstance(){        return Holder.INSTANCE;    }    private static class Holder{        private static final PreloadWebView INSTANCE = new PreloadWebView();    }    /**     * 创建WebView实例     * 用了applicationContext     */    public void preload() {        L.d("webview preload");        Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {            @Override            public boolean queueIdle() {                if (mCachedWebViewStack.size() < CACHED_WEBVIEW_MAX_NUM) {                    mCachedWebViewStack.push(createWebView());                }                return false;            }        });    }    private WebView createWebView() {        WebView webview = new WebView(new MutableContextWrapper(App.getApp()));        webview.getSettings().setJavaScriptEnabled(true);        webview.loadDataWithBaseURL("file:///android_asset/article/?item_id=0&token=0",getHtml(),"text/html","utf-8","file:///android_asset/article/?item_id=0&token=0");        return webview;    }    private static String getHtml() {        StringBuilder builder = new StringBuilder();        builder.append("");        builder.append("");        builder.append("");        builder.append("");        builder.append("");        builder.append("");        builder.append("
");        builder.append("");        builder.append("");        builder.append("");        builder.append("");        return builder.toString();    }    /**     * 从缓存池中获取合适的WebView     *     * @param context activity context     * @return WebView     */    public WebView getWebView(Context context) {        // 为空,直接返回新实例        if (mCachedWebViewStack == null || mCachedWebViewStack.isEmpty()) {            WebView web = createWebView();            MutableContextWrapper contextWrapper = (MutableContextWrapper) web.getContext();            contextWrapper.setBaseContext(context);            return web;        }        WebView webView = mCachedWebViewStack.pop();        // webView不为空,则开始使用预创建的WebView,并且替换Context        MutableContextWrapper contextWrapper = (MutableContextWrapper) webView.getContext();        contextWrapper.setBaseContext(context);        return webView;    }}

本地数据库缓存

使用数据库进行持久化。

图片资源展示

使用 ContentProvider 获取图片资源:

content://com.xposed.toutiao.provider.ImageProvider/getimage/origin/eJy1ku0KwiAUhm8l_F3qvuduJSJ0mRO2JtupiNi9Z4MoWiOa65cinMeX57xXVDda6QPKFld0bLQ9UckbJYlR-UpX3N5Smfi5x3JJ934YxWlKWZhEgbeLhBB-QNFyYUfL1s6uUQFgMkKMtwLA4gJSVwrndUWmUP8CC5xhm87izlKY7VDeTgLXZUtOlJzjkP6AxXfiR5eMYdMCB9PHneGHBzh-VzEje7AzV3ZvHYpjJV599w-uZWXvWadQR_vlAhtY_Bn2LKuzu_GGOscc1MfZ4veyTyNuuu4G1giVqQ==/6694469396007485965/3

上面ContentProvider的uri会调用对应ContentProvider的openFile方法,别忘了在manifest文件中注册。

public class ImageProvider extends ContentProvider {  ...  public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException {    File file = getFile(uri);    return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY) ;  }  ...}

中间字符串使用 zip 压缩,使用以下代码解压 zip 数据:

static final byte[] buffer = new byte[4096];public static final String unzip(String str) {    try {        Inflater inflater = new Inflater();        inflater.setInput(Base64.decode(str, 8));        int size = inflater.inflate(buffer);        inflater.end();        String temp = new String(buffer, 0, size, "UTF-8");        return temp;    } catch (Exception e) {        e.printStackTrace();    }    return "";}

解压后的数据如下:

{    "origin": {        "uri": "large/pgc-image/8e72c19ce0f2456880947531d5bbb230",        "urls": ["http://p1-tt.byteimg.com/large/pgc-image/8e72c19ce0f2456880947531d5bbb230", "http://p1-tt.byteimg.com/large/pgc-image/8e72c19ce0f2456880947531d5bbb230", "http://p3-tt.byteimg.com/large/pgc-image/8e72c19ce0f2456880947531d5bbb230"]    },    "webp_origin": {        "uri": "details/v0/w640/pgc-image/8e72c19ce0f2456880947531d5bbb230.webp",        "urls": ["http://p99.pstatp.com/details/v0/w640/pgc-image/8e72c19ce0f2456880947531d5bbb230.webp", "http://p6-tt.byteimg.com/details/v0/w640/pgc-image/8e72c19ce0f2456880947531d5bbb230.webp", "http://p1-tt.byteimg.com/details/v0/w640/pgc-image/8e72c19ce0f2456880947531d5bbb230.webp"]    },    "thumb": {        "uri": "thumb/pgc-image/8e72c19ce0f2456880947531d5bbb230",        "urls": ["http://p9-tt.byteimg.com/thumb/pgc-image/8e72c19ce0f2456880947531d5bbb230", "http://p3-tt.byteimg.com/thumb/pgc-image/8e72c19ce0f2456880947531d5bbb230", "http://p1-tt.byteimg.com/thumb/pgc-image/8e72c19ce0f2456880947531d5bbb230"]    },    "webp_thumb": {        "uri": "thumb/pgc-image/8e72c19ce0f2456880947531d5bbb230.webp",        "urls": ["http://p1-tt.byteimg.com/thumb/pgc-image/8e72c19ce0f2456880947531d5bbb230.webp", "http://p3-tt.byteimg.com/thumb/pgc-image/8e72c19ce0f2456880947531d5bbb230.webp", "http://p6-tt.byteimg.com/thumb/pgc-image/8e72c19ce0f2456880947531d5bbb230.webp"]    }}

uri的最后两个片段分别代表文章id和图片索引今日头条本地怎么设置,用于通过js通知页面图片加载完成。通过解析content的uri中的数据,获取Fresco下载的缓存文件,返回一个ParcelFileDescriptor对象。结果如下图:

通过以上优化点最终达到的效果如下:

总结

通过今日头条APP的分析,针对特定平台的文章今日头条本地怎么设置,可以采用类似今日头条的方案来预加载数据,提升用户体验。由于时间关系,我们不再分析微信,猜测采用了类似的方案。通过WebView提供的缓存功能和拦截资源方式的缓存体验还是不尽如人意。或许等5G流行起来会好很多。

公众号后台回复关键词:666,即可获得程序员大礼包!

参考

Android Webview H5二次开放方案的实现

腾讯大招VasSonic,让你的H5页面首屏秒开

- -结尾 - -

选择“开发者技术前线”星标,内容触手可及。点击原文,更多惊喜!

开发者技术前沿汇聚技术前沿新闻,关注行业动态。是开发者体验和成长的绝佳指南。

历史推荐

点击观看,解锁更多惊喜!