Android:一个实用的WebView浏览网页,可直接使用

1、前言

无论是日常开发还是练习,相信网页显示是经常需要实现的业务场景,现在的应用一般有网页链接传入,都直接在自己的应用中显示,不会去跳转自带浏览器。今天,我们就来实现一个能满足基本网页浏览需求的页面。国际惯例附上源码

2、效果图

WebView浏览.gif

从图中可以看到进入新闻网页后,除了不能输入网址(关注自己的业务),已经与普通浏览器浏览网页相同。
下面上代码。

3、代码

急用的同学下面可以直接ctrl c + ctrl v,如果想知道一些原理不妨接着往下看

1、添加访问网络权限(AndroidManifest.xml)

<uses-permission android:name="android.permission.INTERNET"/>

2、页面布局

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="app.main.wangliwei.enablehands.view.WebDetailActivity">

    <FrameLayout
        android:id="@+id/web_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:focusable="true"
        android:focusableInTouchMode="true">
    </FrameLayout>

</RelativeLayout>

3、WebDetailActivity.java

public class WebDetailActivity extends AppCompatActivity {
    private Bundle bundle;
    private WebView webView;
    private FrameLayout frameLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_web_detail);

        frameLayout = findViewById(R.id.xwalk_view);
        bundle = getIntent().getExtras();
        initView();
    }

    private void initView() {
        webView = new WebView(this);
        WebSettings settings = webView.getSettings();
        settings.setDomStorageEnabled(true);
        //解决一些图片加载问题
        settings.setJavaScriptEnabled(true);
        settings.setBlockNetworkImage(false);
        webView.setWebViewClient(new WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                Log.d("webview","url: "+url);
                view.loadUrl(url);
                return true;
            }
        });
        frameLayout.addView(webView);
        String url = bundle.getString("URL");
        webView.loadUrl(url);
    }

    //监听BACK按键,有可以返回的页面时返回页面
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if(keyCode == KeyEvent.KEYCODE_BACK) {
            if(webView.canGoBack()) {
                webView.goBack();
                return true;
            }
        }

        return super.onKeyDown(keyCode, event);
    }

    @Override
    protected void onDestroy() {
        if (webView != null) {
            webView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
            webView.setTag(null);
            webView.clearHistory();

            ((ViewGroup) webView.getParent()).removeView(webView);
            webView.destroy();
            webView = null;
        }
        super.onDestroy();
    }
}

在浏览页面时主要做了两个处理,一个是对页面返回的链接(URL)做直接显示处理,由于我是实现一个新闻业务,所以在浏览过程中跳转到其他页面是必须的,重载WebClientView中的shouldOverrideUrlLoading方法。另一个是监听BACK按键,先用canGoBack()判断是否有可以回退的页面,如果有再调用goBack()返回上一个页面。

4、WebView的几种加载方式

  //方式1. 加载一个网页:
  webView.loadUrl("http://www.baidu.com/");

  //方式2:加载apk包中的html页面
  webView.loadUrl("file:///android_asset/test.html");

  //方式3:加载手机本地的html页面
  webView.loadUrl("content://com.android.levi/sdcard/test.html");

5、Settings的常见设置

WebSettings settings=webView.getSettings();
       
// webview启用javascript支持 用于访问页面中的javascript
settings.setJavaScriptEnabled(true);

//设置WebView缓存模式 默认断网情况下不缓存
settings.setCacheMode(WebSettings.LOAD_DEFAULT);


/**
     * LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
     * LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。
     * LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
     * LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。
 */
//断网情况下加载本地缓存
settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);}

//让WebView支持DOM storage API
settings.setDomStorageEnabled(true);

//让WebView支持缩放
settings.setSupportZoom(true);

//启用WebView内置缩放功能
settings.setBuiltInZoomControls(true);

//让WebView支持可任意比例缩放
settings.setUseWideViewPort(true);

//让WebView支持播放插件
settings.setPluginState(WebSettings.PluginState.ON);

//设置WebView使用内置缩放机制时,是否展现在屏幕缩放控件上
settings.setDisplayZoomControls(false);

//设置在WebView内部是否允许访问文件
settings.setAllowFileAccess(true);

//设置WebView的访问UserAgent
settings.setUserAgentString(String string);

//设置脚本是否允许自动打开弹窗
settings.setJavaScriptCanOpenWindowsAutomatically(true);

// 加快HTML网页加载完成速度 
if (Build.VERSION.SDK_INT >= 19) {   
    settings.setLoadsImagesAutomatically(true);
} else {
    settings.setLoadsImagesAutomatically(false); 
}

// 开启Application H5 Caches 功能 
settings.setAppCacheEnabled(true); 

// 设置编码格式
settings.setDefaultTextEncodingName("utf-8");

3、跳转Activity

拿到链接(URL)以后可以这样开启浏览页面

   Bundle bundle = new Bundle();
   bundle.putString("URL",url);
   Intent intent = new Intent(getActivity(),WebDetailActivity.class);
   intent.putExtras(bundle);
   startActivity(intent,bundle);

4、关于内存泄漏

每个应用在android中所占用的内存是有限制的,碰巧WebView又是内存大户,所以在关闭页面时,如果不及时释放内存,很可能导致OOM。

避免内存泄漏要做一些处理:
不在xml中定义 Webview ,而是在需要的时候在Activity中创建,并且Context使用 getApplicationgContext(),因为WebView调用destory时,如果传入Activity的Context对象WebView会仍绑定在Activity上。在 Activity 销毁( WebView )的时候,先让 WebView 加载null内容,然后从父容器(ViewGroup)中移除 WebView,再销毁 WebView,最后置空。

需要注意的是,如果你需要在WebView中打开链接或者你打开的页面带有flash,获得你的WebView想弹出一个dialog,都会导致从ApplicationContext到ActivityContext的强制类型转换错误,从而导致你应用崩溃。这是因为在加载flash的时候,系统会首先把你的WebView作为父控件,然后在该控件上绘制flash,他想找一个Activity的Context来绘制他,但是你传入的是ApplicationContext。

解决方法:通常根治这个问题的办法是为WebView开启另外一个进程,通过AIDL与主进程进行通信,WebView所在的进程可以根据业务的需要选择合适的时机进行销毁,从而达到内存的完整释放。因为webview引发的 资源无法释放等问题 全部可以解决。

5、最后

通过以上步骤还是可以实现一个满足基本浏览需求的页面的,注意内存泄漏,比较开发到后期,对内存的使用时越来也关注。如果对你有帮助,欢迎 star 支持下,源码地址,个人项目里面有一些其他东西,直接看WebDetailActivity中的内容即可。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容