WebView相关

WebView详解
本文详细介绍了WebView的使用方法,包括实现后退功能的两种方式、通过Intent打开网页、设置WebSettings选项、加载不同类型的资源、自定义WebViewClient和WebChromeClient以增强交互体验。

WebView相关


WebView的后退

方式一

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
        if (mWebView.canGoBack()) {
            mWebView.goBack();
        } else {
            finish();
        }
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

方式二

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if ((keyCode == KeyEvent.KEYCODE_BACK) && webview.canGoBack()) {
        webview.goBack();
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

使用intent跳转到指定网页

Uri uri = Uri.parse("http://www.sohu.com");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);

webview浏览器url输入栏

btn_search.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        String url = et_text.getText().toString();

        if (url == null || "".equals(url)) {
            Toast.makeText(getApplicationContext(), "请输入", Toast.LENGTH_SHORT).show();
        } else {
            if (!url.startsWith("http:") && !url.endsWith("file:")) {
                url = "http://" + url;
            }
        }
        webview.loadUrl(url);
    }
});

WebSettings设置

settings = mWebView.getSettings();
settings.setJavaScriptEnabled(true); // 启用javascript脚本
settings.setBuiltInZoomControls(true); // 启用界面上放大和缩小按钮
settings.setUseWideViewPort(true); // 启用双击放大, 双击缩小功能
mWebView.loadUrl(url);

webSettings.setCacheMode(webSettings.LOAD_CACHE_ELSE_NETWORK);// 优先使用缓存
webSettings.setCacheMode(webSettings.LOAD_NO_CACHE);//不使用缓存
webview.setHapticFeedbackEnabled(false); // 触觉回馈不可用
mWebSettings.setSupportZoom(true); // 支持缩放
webview.getSettings().setSavePassword(false); // 设置是否保存密码

webview加载资源

// webview加载本地资源
webview.loadUrl("file:///android_asset/demo.html");

// 加载web资源
webview.loadUrl("http://baidu.com");

// 这种方式可以解决中文乱码问题
String htmlContent="<html><head></head><body>少量内容,直接用字符串拼接</body></html>";
webview.loadDataWithBaseURL(null, htmlContent, "text/html", "utf-8", null);

WebViewClient

使用webview打开网页

webview.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        view.loadUrl(url);

        // 返回true用WebView打开,false调用系统浏览器或第三方浏览器
        return true;
    }
});

加载网页完成后,进度条消失

mWebView.setWebViewClient(new WebViewClient() {
    @Override
    public void onPageFinished(WebView view, String url) {
        mProgressbar.setVisibility(View.GONE);
    }
});

总结

class MyWebViewClient extends WebViewClient {
    //设置使用webview打开网页
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        view.loadUrl(url);
        return true;
    }

    // 开始加载网页时要做的工作
    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
        super.onPageStarted(view, url, favicon);
    }

    // 加载完成时要做的工作
    @Override
    public void onPageFinished(WebView view, String url) {
        super.onPageFinished(view, url);
    }

    // 加载错误时要做的工作
    @Override
    public void onReceivedError(WebView view, int errorCode,
            String description, String failingUrl) {
        Log.d("onReceivedError", "error=" + description);
        Toast.makeText(MainActivity.this, errorCode + "/" + description,
                Toast.LENGTH_LONG).show();
    }

}

WebChromeClient

class MyWebChromeClient extends WebChromeClient {

    // 对话框
    @Override
    public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
        Builder builder = new Builder(MainActivity.this);
        builder.setTitle("提示对话框");
        builder.setMessage("message");
        builder.setPositiveButton(android.R.string.ok, new AlertDialog.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                result.confirm();
            }
        });
        builder.setCancelable(false);
        builder.create();
        builder.show();
        return true;
    }

    // 带按钮的对话框
    @Override
    public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
        Builder builder = new Builder(MainActivity.this);
        builder.setTitle("带选择的对话框");
        builder.setMessage(message);
        builder.setPositiveButton(android.R.string.ok, new AlertDialog.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                result.confirm();
            }
        });
        builder.setNeutralButton(android.R.string.cancel, new AlertDialog.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                result.cancel();
            }
        });
        builder.setCancelable(false);
        builder.create();
        builder.show();
        return true;
    }

    // 带输入框的对话框
    @Override
    public boolean onJsPrompt(WebView view, String url, String message, String defaultValue,
            final JsPromptResult result) {

        LayoutInflater inflater = LayoutInflater.from(MainActivity.this);
        final View v = inflater.inflate(R.layout.prom_dialog, null);

        // 设置 TextView对应网页中的提示信息
        TextView TextView_PROM = (TextView) v.findViewById(R.id.TextView_PROM);
        TextView_PROM.setText(message);
        // 设置EditText对应网页中的输入框
        EditText EditText_PROM = (EditText) v.findViewById(R.id.EditText_PROM);
        EditText_PROM.setText(defaultValue);

        Builder builder = new Builder(MainActivity.this);
        builder.setTitle("带输入的对话框");
        builder.setView(v);
        builder.setPositiveButton(android.R.string.ok, new AlertDialog.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                String value = ((EditText) v.findViewById(R.id.EditText_PROM)).getText().toString();
                result.confirm(value);
            }
        });
        builder.setNegativeButton(android.R.string.cancel, new AlertDialog.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                result.cancel();
            }
        });
        builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
            @Override
            public void onCancel(DialogInterface dialog) {
                result.cancel();
            }
        });
        builder.create();
        builder.show();
        return true;
    }

    // 设置网页加载的进度条
    @Override
    public void onProgressChanged(WebView view, int newProgress) {
        MainActivity.this.getWindow().setFeatureInt(Window.FEATURE_PROGRESS, newProgress * 100);
        super.onProgressChanged(view, newProgress);
    }

    // 设置应用程序的标题
    @Override
    public void onReceivedTitle(WebView view, String title) {
        MainActivity.this.setTitle(title);
        super.onReceivedTitle(view, title);
    }

}
<think>好的,我现在需要准备关于WebView的面试题。首先,我得回忆一下自己学过的WebView相关知识,可能包括基本概念、使用场景、常见问题及优化方法等。记得WebView是用于在应用中嵌入网页的组件,比如Android的WebView和iOS的UIWebView/WKWebView。不过可能用户更关注Android方面的内容,因为面试题通常分平台。 接下来,我应该整理常见的面试问题。例如,WebView的基本用法,如何加载网页,与JavaScript的交互,性能优化,安全漏洞,缓存机制等。还可能涉及混合开发模式,比如Hybrid App的原理,JSBridge的实现。另外,内存泄漏问题和WebView的版本差异(比如Android中WebView内核的变化)也是常见考点。 然后,每个问题需要详细展开。比如,与JS交互部分,可能需要说明如何通过addJavascriptInterface或evaluateJavascript进行通信。性能优化方面,可能提到硬件加速、资源预加载、缓存策略等。安全方面,需注意远程代码执行漏洞,如CVE-2014-6041,以及如何防范,比如限制JS执行、过滤输入等。 同时,要注意实际开发中的经验,比如WebViewClient和WebChromeClient的区别,如何处理页面加载的各种事件,如何处理错误和重试机制。另外,WebView的缓存机制,如缓存模式设置,清除缓存的方法也是常见问题。 可能还需要比较不同版本的WebView,比如Android 4.4之前使用WebKit内核,之后转为Chromium内核,带来的变化和兼容性问题。以及如何选择合适的WebView版本,处理不同系统版本的适配。 此外,混合开发中的常见问题,比如WebView和原生应用的通信方式,JSBridge的设计,如何保证通信的安全性和效率。还有WebView加载速度的优化,比如资源本地化、延迟加载、并行加载等策略。 还要考虑面试官可能深入追问的点,比如WebView的内存泄漏如何检测和解决,如何实现离线缓存,如何处理Cookie同步问题,以及WebView的线程模型,是否在主线程操作等。 需要确保覆盖全面,但也要结构清晰,分点列出,方便记忆和回答。可能的问题列表: 1. WebView的基本使用和常用方法。 2. WebView与JavaScript的交互方式。 3. WebView的性能优化策略。 4. WebView的安全问题及防范措施。 5. WebView的缓存机制及实现。 6. 如何处理WebView的内存泄漏? 7. 混合开发中JSBridge的实现原理。 8. WebViewClient和WebChromeClient的区别。 9. WebView在不同Android版本上的差异。 10. WebView加载速度慢的优化方法。 每个问题需要准备简明扼要的回答,并举例说明。例如,在JS交互中,Android可以通过@JavascriptInterface注解方法,允许JS调用原生代码,而原生代码可以通过loadUrl或evaluateJavascript执行JS函数。 在性能优化方面,可以提到启用硬件加速、使用WebView缓存、资源预加载、减少同步通信等。安全方面,需避免任意JS执行,处理Intent Scheme漏洞,以及正确设置文件访问权限。 另外,内存泄漏常见于WebView持有Activity引用,应在onDestroy时将其从父容器移除并置为null。对于WebView的版本差异,可能需要处理不同内核的兼容性问题,比如CSS或JS的兼容性处理。 总结来说,需要系统性地整理WebView的各个知识点,结合实际开发中的问题和解决方案,确保回答时既有理论又有实践经验支撑。可能还需要查阅一些资料,确认某些细节的正确性,比如具体的API使用方式或安全漏洞的编号,避免出现错误。</think>以下整理了WebView相关的高频面试题及核心知识点,方便快速掌握重点: --- ### **1. WebView基础概念** - **作用**:在App内嵌入浏览器引擎,展示网页内容(如Hybrid App)。 - **Android关键类**: - `WebView`:负责渲染网页。 - `WebViewClient`:处理页面加载、错误处理等事件。 - `WebChromeClient`:处理JS对话框、进度条等。 --- ### **2. 加载网页流程** ```java WebView webView = findViewById(R.id.webview); webView.getSettings().setJavaScriptEnabled(true); // 启用JS webView.loadUrl("https://example.com"); ``` --- ### **3. 与JavaScript交互** - **JS调用原生**: ```java // Android端注册接口 webView.addJavascriptInterface(new JsInterface(), "Android"); public class JsInterface { @JavascriptInterface public void showToast(String msg) { ... } } ``` ```javascript // JS端调用 Android.showToast("Hello"); ``` - **原生调用JS**: ```java webView.evaluateJavascript("javascript:updateData('" + data + "')", null); ``` --- ### **4. 性能优化策略** - **硬件加速**:在Manifest中为Activity设置`android:hardwareAccelerated="true"`。 - **缓存机制**: ```java webView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); ``` - **资源预加载**:提前初始化WebView,加载常用资源。 - **独立进程**:防止内存泄漏影响主进程。 --- ### **5. 内存泄漏处理** - **原因**:WebView持有Activity引用,未及时销毁。 - **解决**: ```java @Override protected void onDestroy() { webView.stopLoading(); webView.destroy(); webView = null; super.onDestroy(); } ``` --- ### **6. 安全防护** - **漏洞**: - **CVE-2014-6041**:远程代码执行(旧版本WebView)。 - **任意文件访问**:通过`file://`协议访问本地文件。 - **措施**: - 限制JS执行:`setJavaScriptEnabled(false)`(按需开启)。 - 过滤恶意URL:重写`shouldOverrideUrlLoading`。 - 禁止文件访问:`webView.getSettings().setAllowFileAccess(false)`。 --- ### **7. 缓存机制详解** - **缓存类型**: - 页面缓存:`LOAD_CACHE_ELSE_NETWORK`(优先缓存)。 - DOM Storage:存储结构化数据。 - IndexedDB:客户端数据库。 - **清除缓存**: ```java webView.clearCache(true); CookieManager.getInstance().removeAllCookies(null); ``` --- ### **8. WebViewClient vs WebChromeClient** - **WebViewClient**: - 处理页面生命周期(如`onPageStarted`, `onPageFinished`)。 - 拦截URL请求(`shouldOverrideUrlLoading`)。 - **WebChromeClient**: - 处理JS弹窗(`onJsAlert`, `onJsConfirm`)。 - 获取网页标题、加载进度。 --- ### **9. 混合开发(Hybrid)核心** - **JSBridge原理**: 1. 定义原生与JS通信协议(如URL Scheme)。 2. 通过`shouldOverrideUrlLoading`拦截自定义协议。 3. 解析参数执行对应原生方法。 --- ### **10. 高频面试题** 1. **WebView加载白屏可能原因?** - 网络延迟、JS阻塞、硬件加速未开启。 2. **如何实现WebView的离线缓存?** - 使用`Service Worker`或拦截请求返回本地资源。 3. **WebView线程模型注意事项?** - WebView方法需在主线程调用,JS回调可能运行在子线程。 --- 掌握以上知识点,能覆盖90%的WebView面试场景。建议结合实际项目经验(如优化案例、安全漏洞修复)增强回答深度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值