Android爬坑之旅之WebView

不知不觉,Hybird App已经成了目前比较主流的一种开发方式。

对于用户体验要求较高或者与硬件交互较多的功能我们一般都会采用Native原生的方式来实现。 而用户交互少,偏展示类,活动类的功能我们则通常采用H5的方式来实现, 例如新闻类的app,详情展示页一般就是H5的页面

  • 一方面图文排版上web有着先天的优势,同时纯展示类的页面在目前的移动设备上,性能体验已经很难让用户分辨是网页还是原生了;
  • 另一方面,H5的页面跨平台,方便在原生客户端上实现分享功能,拥有较强的传播性,我们平时常见的活动页面也拥有这样的优势,所以你看到的活动页面也基本都是H5,只需轻轻一点就能分享到各个平台;
  • 同时,H5的页面开发降低了开发成本,一套代码,web,android,ios都能访问。(然而实际开发过程中,H5的适配也都是各种泪)

既然Hybird App有这么多优势,那在Android中我们通过什么样的方式在原生项目中嵌入H5页面呢?

那就不得不提到我们的WebVew了,作为官方唯一用来显示web的组件, 展示网页这样的任务也只能交给它了。

A View that displays web pages. This class is the basis upon which you can roll your own web browser or simply display some online content within your Activity. It uses the WebKit rendering engine to display web pages and includes methods to navigate forward and backward through a history, zoom in and out, perform text searches and more.

引用官方文档的一句话: WebView是一个用来在Activity中显示我们网页的视图组件,它通过webkit渲染引擎渲染和显示我们的web页面,并且包含了web的历史导航操法,页面放大缩小,文本搜索等方法。

我们首先来看一下WebView的基本用法:

#WebView的基本用法


关于WebView的基本用法,大部分人也是轻车熟路, 本来也是写了一部分,无意中发现有位博主的博客对WebView的介绍实在太过详细,像我这样的懒人,有更好的文章是不会自己去写的, 所以删了自己写的,将大牛博主的博客分享出来,感兴趣同学的可以一起看一看:

Android WebView 开发详解(一)  Android WebView 开发详解(二) Android WebView 开发详解(三)

了解完WebView的基本用法,那就来总结下最近项目中遇到的关于WebView的坑

#项目中使用WebView遇到的问题


###WebView界面的原生标题设置

如图所示, 一般情况下,我们WebView所在界面由顶部带标题的原生导航栏WebView的内容部分组成, 而WebView中的界面可能在点击后还会再跳其他Web页面(如图点击请假会在当前WebView跳转请假的Web页面)。

由于点击内容的不确定性,所以通常情况下,最简单的做法就是捕获h5页面的 标签来进行标题设置。

对于捕获 </a> 标签内容的方式,WebView也很好地提供了支持,我们可以通过继承WebChromeClient的onReceivedTitle来进行获取:</p> <pre><code lang="bash" class="hljs bash"> private class WebViewChromeClient extends WebChromeClient { @Override public void onReceivedTitle(WebView view, String title) { super.onReceivedTitle(view, title); mTitleText.setTitle(String.valueOf(view.getTitle())); } } </code></pre><p>然而这样的方式在实际使用中有一个问题:</p> <p>当通过 <a href="https://developer.android.google.cn/reference/android/webkit/WebView.html#goBack()" target="_blank">webView.goBack()</a> 方式返回上一级Web页面的时候不会触发这个方法,因此会导致标题无法跟随历史记录返回上一级页面。</p> <p>所以在项目中, 我们可以通过重写 <a href="https://developer.android.google.cn/reference/android/webkit/WebViewClient.html" target="_blank">WebViewClient</a> 的 [onPageFinished](https://developer.android.google.cn/reference/android/webkit/WebViewClient.html#onPageFinished(android.webkit.WebView, java.lang.String)) 方法,在 [onPageFinished](https://developer.android.google.cn/reference/android/webkit/WebViewClient.html#onPageFinished(android.webkit.WebView, java.lang.String)) 中对界面标题进行设置。 因为不管是历史记录的返回还是点击跳转都会触发页面加载, 当页面加载完成时(不包括js动态创建以及img图片加载完毕)都会触发 [onPageFinished](https://developer.android.google.cn/reference/android/webkit/WebViewClient.html#onPageFinished(android.webkit.WebView, java.lang.String)) 这个方法, 此时我们去获取 <a href="" target="_blank"><title></a> 的标题内容不会有任何问题,可以确保在页面返回时能够获取到正确的标题。</p> <pre><code lang="bash" class="hljs bash"> mWebView.setWebViewClient(new <span class="hljs-function"><span class="hljs-title">WebViewClient</span></span>(){ //Web页面每次加载并完成时会触发该方法 @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); mToolbar.setTitle(String.valueOf(view.getTitle())); Log.i (LOG_TAG, <span class="hljs-string">"onPageFinished"</span>); } }); </code></pre><p><strong>注: 这种做法有一个缺陷,就是返回上一个界面的时候,等页面加载完成的时候标题才会显示出来,为了更好地优化,我们可以创建一个集合用来保存我们的标题,加载url的时候把标题添加进集合,当返回上一级页面的时候,从集合中取出标题进行显示,同时从集合中移除标题。</strong></p> <hr> <p>###WebView中的Web页面存在<input type='file'>标签时无法打开文件选择器</p> <p>在我们的手机浏览器中,当web页面中有 <a href="" target="_blank"><input type='file'></a> 按钮标签的时候点击会自动打开系统的文件选择器, 然而这个功能在主流系统的WebView中没有被默认实现, 因此,为了让 <a href="" target="_blank"><input type='file'></a> 点击时能够打开系统的文件选择器, 我们必须通过重写 <a href="https://developer.android.google.cn/reference/android/webkit/WebChromeClient.html" target="_blank">WebChromeClient</a> 来实现点击<a href="" target="_blank"><input type='file'></a> 打开系统文件选择器。 代码如下:</p> <pre><code lang="bash" class="hljs bash">public class MainActivity extends AppCompatActivity { /** Android 5.0以下版本的文件选择回调 */ protected ValueCallback<Uri> mFileUploadCallbackFirst; /** Android 5.0及以上版本的文件选择回调 */ protected ValueCallback<Uri[]> mFileUploadCallbackSecond; protected static final int REQUEST_CODE_FILE_PICKER = 51426; protected String mUploadableFileTypes = <span class="hljs-string">"image/*"</span>; private WebView mWebView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); <span class="hljs-built_in">set</span>ContentView(R.layout.activity_main); initWebView(); } private void <span class="hljs-function"><span class="hljs-title">initWebView</span></span>() { mWebView = (WebView) findViewById(R.id.my_webview); mWebView.loadUrl(<span class="hljs-string">"file:///android_asset/index.html"</span>); mWebView.setWebChromeClient(new OpenFileChromeClient()); } private class OpenFileChromeClient extends WebChromeClient { // Android 2.2 (API level 8)到Android 2.3 (API level 10)版本选择文件时会触发该隐藏方法 @SuppressWarnings(<span class="hljs-string">"unused"</span>) public void openFileChooser(ValueCallback<Uri> uploadMsg) { openFileChooser(uploadMsg, null); } // Android 3.0 (API level 11)到 Android 4.0 (API level 15))版本选择文件时会触发,该方法为隐藏方法 public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) { openFileChooser(uploadMsg, acceptType, null); } // Android 4.1 (API level 16) -- Android 4.3 (API level 18)版本选择文件时会触发,该方法为隐藏方法 @SuppressWarnings(<span class="hljs-string">"unused"</span>) public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) { openFileInput(uploadMsg, null, <span class="hljs-literal">false</span>); } // Android 5.0 (API level 21)以上版本会触发该方法,该方法为公开方法 @SuppressWarnings(<span class="hljs-string">"all"</span>) public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) { <span class="hljs-keyword">if</span> (Build.VERSION.SDK_INT >= 21) { final boolean allowMultiple = fileChooserParams.getMode() == FileChooserParams.MODE_OPEN_MULTIPLE;//是否支持多选 openFileInput(null, filePathCallback, allowMultiple); <span class="hljs-built_in">return</span> <span class="hljs-literal">true</span>; } <span class="hljs-keyword">else</span> { <span class="hljs-built_in">return</span> <span class="hljs-literal">false</span>; } } } @SuppressLint(<span class="hljs-string">"NewApi"</span>) protected void openFileInput(final ValueCallback<Uri> fileUploadCallbackFirst, final ValueCallback<Uri[]> fileUploadCallbackSecond, final boolean allowMultiple) { //Android 5.0以下版本 <span class="hljs-keyword">if</span> (mFileUploadCallbackFirst != null) { mFileUploadCallbackFirst.onReceiveValue(null); } mFileUploadCallbackFirst = fileUploadCallbackFirst; //Android 5.0及以上版本 <span class="hljs-keyword">if</span> (mFileUploadCallbackSecond != null) { mFileUploadCallbackSecond.onReceiveValue(null); } mFileUploadCallbackSecond = fileUploadCallbackSecond; Intent i = new Intent(Intent.ACTION_GET_CONTENT); i.addCategory(Intent.CATEGORY_OPENABLE); <span class="hljs-keyword">if</span> (allowMultiple) { <span class="hljs-keyword">if</span> (Build.VERSION.SDK_INT >= 18) { i.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, <span class="hljs-literal">true</span>); } } i.setType(mUploadableFileTypes); startActivityForResult(Intent.createChooser(i, <span class="hljs-string">"选择文件"</span>), REQUEST_CODE_FILE_PICKER); } public void onActivityResult(final int requestCode, final int resultCode, final Intent intent) { <span class="hljs-keyword">if</span> (requestCode == REQUEST_CODE_FILE_PICKER) { <span class="hljs-keyword">if</span> (resultCode == Activity.RESULT_OK) { <span class="hljs-keyword">if</span> (intent != null) { //Android 5.0以下版本 <span class="hljs-keyword">if</span> (mFileUploadCallbackFirst != null) { mFileUploadCallbackFirst.onReceiveValue(intent.getData()); mFileUploadCallbackFirst = null; } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (mFileUploadCallbackSecond != null) {//Android 5.0及以上版本 Uri[] dataUris = null; try { <span class="hljs-keyword">if</span> (intent.getDataString() != null) { dataUris = new Uri[] { Uri.parse(intent.getDataString()) }; } <span class="hljs-keyword">else</span> { <span class="hljs-keyword">if</span> (Build.VERSION.SDK_INT >= 16) { <span class="hljs-keyword">if</span> (intent.getClipData() != null) { final int numSelectedFiles = intent.getClipData().getItemCount(); dataUris = new Uri[numSelectedFiles]; <span class="hljs-keyword">for</span> (int i = 0; i < numSelectedFiles; i++) { dataUris[i] = intent.getClipData().getItemAt(i).getUri(); } } } } } catch (Exception ignored) { } mFileUploadCallbackSecond.onReceiveValue(dataUris); mFileUploadCallbackSecond = null; } } } <span class="hljs-keyword">else</span> { //这里mFileUploadCallbackFirst跟mFileUploadCallbackSecond在不同系统版本下分别持有了 //WebView对象,在用户取消文件选择器的情况下,需给onReceiveValue传null返回值 //否则WebView在未收到返回值的情况下,无法进行任何操作,文件选择器会失效 <span class="hljs-keyword">if</span> (mFileUploadCallbackFirst != null) { mFileUploadCallbackFirst.onReceiveValue(null); mFileUploadCallbackFirst = null; } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (mFileUploadCallbackSecond != null) { mFileUploadCallbackSecond.onReceiveValue(null); mFileUploadCallbackSecond = null; } } } } } </code></pre><p><strong>注:当用户点击input file弹出文件选择器后,点击取消或者返回按钮没有执行选择时,必须在onActivityResult里给valueCallback的onReceiveValue传null,因为valueCallback持有的是WebView,在onReceiveValue没有回传值的情况下,WebView无法进行下一步操作,会导致取消选择文件后,点击input file不会再响应:</strong></p> <pre><code lang="bash" class="hljs bash"> <span class="hljs-keyword">if</span> (mFileUploadCallbackFirst != null) { mFileUploadCallbackFirst.onReceiveValue(null); mFileUploadCallbackFirst = null; } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (mFileUploadCallbackSecond != null) { mFileUploadCallbackSecond.onReceiveValue(null); mFileUploadCallbackSecond = null; } </code></pre><p>示例demo地址: https://github.com/cjpx00008/FileChooser4WebViewDemo</p> <hr> <p>###WebView中的web页面调用系统选择器或者相机导致app进入后台被系统释放</p> <p>众所周知,WebView基于webkit内核来渲染web页面,因此使用起来相当于一个小型浏览器,即使页面内容不复杂,只要使用WebView也会占用大量的内存。</p> <p>而Android的内存回收机制,在系统内存不足的情况下会优先释放内存占用较大的app从而回收内存资源,此时正在使用WebView的运行在后台的app肯定是首当其冲被回收的。</p> <p>因此,当WebView通过input file调用系统文件选择器,或者通过文件选择器调用了相机时,我们的app就进入了后台,在部分低端Android设备(尤其红米这类手机,默认的神隐模式会在app进入后台的时候较大概率的释放app)或者系统内存资源不足的情况下,我们的app就会优先被释放掉,导致文件选择完毕后,回到上一界面时,app的界面重新走了onCreate,web页面也因此重建了。</p> <p>对于部分需要填写大量表单的web页面来说,用户填写的数据会随着界面的销毁重建而丢失,而选择的文件也因为页面的重建而无法回传给input file,这对于用户的体验来说肯定是不友好的。</p> <p>也许你会说,重写onSaveInstance保存数据就是啦。 这也是我一开始考虑的, 我们的WebView也提供了 <a href="https://developer.android.google.cn/reference/android/webkit/WebView.html#saveState(android.os.Bundle)" target="_blank">saveState</a> 以及 <a href="https://developer.android.google.cn/reference/android/webkit/WebView.html#restoreState(android.os.Bundle)" target="_blank">restoreState</a> 来保存状态。</p> <p>然而悲催的是,这两个方法并不会保存web页面内的数据,它只保存了WebView加载的页面,前进后退的历史状态等数据。</p> <p>引用官方文档的描述:</p> <blockquote> <p>Saves the state of this WebView used in <a href="https://developer.android.google.cn/reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle)" target="_blank">onSaveInstanceState(Bundle)</a> . Please note that this method no longer stores the display data for this WebView. The previous behavior could potentially leak files if <a href="https://developer.android.google.cn/reference/android/webkit/WebView.html#restoreState(android.os.Bundle)" target="_blank">restoreState(Bundle)</a>  was never called.</p> </blockquote> <p><strong>Please note that this method no longer stores the display data for this WebView</strong></p> <p>WebView的saveState并不会保存界面的数据。</p> <p>所以,对于表单数据的恢复,我们只能自己想办法了,我们这里采用了两套方案:</p> <ol> <li>通过WebView与JS交互,在onSaveInstance的时候触发界面保存数据,保存数据的方式也大体分为两种, 一种使用H5自带的localStorage来进行数据存储,页面销毁重建的时候H5页面判断本地localStorage数据是否有值,有就将值重新填充到页面表单,提交数据后清除本地localStorage的数据。 这种方式需要给WebView开启对localStorage的支持。</li> </ol> <pre><code lang="bash" class="hljs bash">WebSettings settings = mWebView.getSettings(); settings.setDomStorageEnabled(<span class="hljs-literal">true</span>); </code></pre><p>另一种则提供JS接口将数据传递给原生,通过原生代码将数据保存到本地,在页面重建渲染完成时,web页面通过JS接口调用原生方法拉取数据判断是否有值,有则填充表单,无则不做操作,提交数据后调用JS接口调用原生方法清空本地数据。</p> <ol start="2"> <li>由web端自己处理,在表单页面文本输入失去焦点时自动保存数据,页面销毁重建时,自己拉取数据进行判断。 这种方式对原生的依赖较低,个人更倾向这种方式,当然最终由于项目的特殊情况,我们还是采用了第一种方式。</li> </ol> <p>以上是表单数据的恢复方案,</p> <p>而对于从系统文件选择器选择的文件web页面是无法直接接收并处理了,这里我们提供了一个JS接口在web页面加载完成时,进行触发,并将数据传递给web页面。</p> <p>说到这里,不得不提另外一个问题</p> <hr> <p>###WebView调用服务端页面如何访问本地文件</p> <p>上面我们提到了通过JS接口将选择的文件数据传递给web页面,</p> <p>然而由于安全原因,WebView限制了远程url页面访问本地文件, 如果我们加载的url是服务端的页面,那我们没有任何办法直接通过文件地址来访问客户端本地的文件</p> <p>我们知道,WebView用来加载网页的方式主要有三种:</p> <pre><code lang="bash" class="hljs bash">loadUrl(String url) loadUrl(String url, Map<String, String> additionalHttpHeaders) </code></pre><pre><code lang="bash" class="hljs bash">loadData(String data, String mimeType, String encoding) </code></pre><pre><code lang="bash" class="hljs bash">loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String <span class="hljs-built_in">history</span>Url) </code></pre><p>[loadData()](https://developer.android.google.cn/reference/android/webkit/WebView.html#loadData(java.lang.String, java.lang.String, java.lang.String)) 和 [loadDataWithBaseURL()](https://developer.android.google.cn/reference/android/webkit/WebView.html#loadDataWithBaseURL(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)) 都是直接将数据加载进WebView中,相当于显示的一个本地Web</p> <p>loadUrl也可以通过访问本地的文件地址(例如本地asset目录下的存放了index.html页面,可以通过<code>loadUrl("file:///android_asset/index.html")</code>来显示web页面)</p> <p>对于这样的三种加载本地内容的方式,我们可以使用多种方式来传递路径供web页面传递,这里以图片为例(相册目录下test/IMG_20170105_093405.jpg):</p> <ol> <li>直接通过文件的绝对地址来提供给页面显示:</li> </ol> <pre><code lang="bash" class="hljs bash"><img src = <span class="hljs-string">'file:///storage/emulated/0/dcim/test/IMG_20170105_093405.jpg'</span> /> </code></pre><ol start="2"> <li>通过媒体库查询出来的content uri地址展示</li> </ol> <pre><code lang="bash" class="hljs bash"><img src = <span class="hljs-string">'content://media/external/images/media/102610'</span> /> </code></pre><ol start="3"> <li>通过FileProvider转换的content uri地址展示</li> </ol> <pre><code lang="bash" class="hljs bash"><img src = <span class="hljs-string">'content://com.test.myfileprovider/dcim/test/IMG_20170105_093405.jpg'</span>/> </code></pre><p>可当你使用loadUrl(String url)加载服务端的http地址时,以上三种方法将均无法使用,经过各种尝试,目前找到两种方案来提供给web端进行图片显示:</p> <ol> <li> <p>由原生代码处理,将文件流转换为Base64之后通过JS接口回传给web;</p> </li> <li> <p>重写WebViewClient里的shouldInterceptRequest方法,每当页面发生资源请求的时候就会触发这个方法,我们可以过滤请求,判断请求是否为本地文件,通过拦截请求转换为二进制流回传回去, 示例代码如下:</p> </li> </ol> <pre><code lang="bash" class="hljs bash">mWebView.setWebViewClient(new <span class="hljs-function"><span class="hljs-title">WebViewClient</span></span>(){ @Override public WebResourceResponse shouldInterceptRequest(WebView view, String url) { <span class="hljs-keyword">if</span> (url.startsWith(<span class="hljs-string">"http://"</span>)&&url.endWith(<span class="hljs-string">".jpg"</span>) { <span class="hljs-built_in">return</span> getWebResourceResponse(<span class="hljs-string">"/storage/emulated/0/dcim/trinaic/IMG_20170105_093405.jpg"</span>, <span class="hljs-string">"image/jpeg"</span>, <span class="hljs-string">".jpg"</span>); } <span class="hljs-built_in">return</span> super.shouldInterceptRequest(view, url); } } private WebResourceResponse getWebResourceResponse(String url, String mime, String style) { WebResourceResponse response = null; try { response = new WebResourceResponse(mime, <span class="hljs-string">"UTF-8"</span>, new FileInputStream(new File(url))); } catch (FileNotFoundException e) { e.printStackTrace(); } <span class="hljs-built_in">return</span> response; } </code></pre><hr> <p>###WebView JS注入漏洞</p> <p>要想让原生跟JS进行交互,按照官方提供的方法就得使用addJavaScriptInterface</p> <pre><code lang="bash" class="hljs bash">class JsObject { @JavascriptInterface public String <span class="hljs-function"><span class="hljs-title">toString</span></span>() { <span class="hljs-built_in">return</span> <span class="hljs-string">"injectedObject"</span>; } } webView.addJavascriptInterface(new JsObject(), <span class="hljs-string">"injectedObject"</span>); webView.loadData(<span class="hljs-string">""</span>, <span class="hljs-string">"text/html"</span>, null); webView.loadUrl(<span class="hljs-string">"javascript:alert(injectedObject.toString())"</span>); </code></pre><blockquote> <p>Injects the supplied Java object into this WebView. The object is injected into the JavaScript context of the main frame, using the supplied name. This allows the Java object's methods to be accessed from JavaScript. For applications targeted to API level <a href="https://developer.android.google.cn/reference/android/os/Build.VERSION_CODES.html#JELLY_BEAN_MR1" target="_blank">JELLY_BEAN_MR1</a>  and above, only public methods that are annotated with <a href="https://developer.android.google.cn/reference/android/webkit/JavascriptInterface.html" target="_blank">JavascriptInterface</a>  can be accessed from JavaScript. For applications targeted to API level <a href="https://developer.android.google.cn/reference/android/os/Build.VERSION_CODES.html#JELLY_BEAN" target="_blank">JELLY_BEAN</a>  or below, all public methods (including the inherited ones) can be accessed, see the important security note below for implications.</p> </blockquote> <p>引用官方api的说明,在Android 4.2以下,会有被注入的风险,4.2以上版本可以通过<code>@JavascriptInterface</code>的注解来处理这个问题。 具体的注入方式,我找了篇博客,如果有不清楚的同学可以了解下: <a href="http://blog.csdn.net/leehong2005/article/details/11808557/" target="_blank">Android WebView的Js对象注入漏洞解决方案</a></p> <p>在之前乌云平台报出的漏洞中, android/webkit/webview中默认内置的一个searchBoxJavaBridge_ 接口同时存在远程代码执行漏洞</p> <p>在于android/webkit/AccessibilityInjector.java中,调用了此组件的应用在开启辅助功能选项中第三方服务的安卓系统中会造成远程代码执行漏洞。这两个接口分别是"accessibility" 和"accessibilityTraversal" ,此漏洞原理与searchBoxJavaBridge_接口远程代码执行相似,均为未移除不安全的默认接口,不过此漏洞需要用户启动系统设置中的第三方辅助服务,利用条件较复杂。</p> <p>因此,一般情况下我们通过removeJavaScripteInterface来移除这几个接口</p> <pre><code lang="bash" class="hljs bash"> <span class="hljs-keyword">if</span> (Build.VERSION.SDK_INT < 17) { mAdvanceWebView.removeJavascriptInterface(<span class="hljs-string">"searchBoxJavaBridge_"</span>); mAdvanceWebView.removeJavascriptInterface(<span class="hljs-string">"accessibility"</span>); mAdvanceWebView.removeJavascriptInterface(<span class="hljs-string">"accessibilityTraversal"</span>); } </code></pre><p>除此之外也有通过onJsPrompt的方式来实现WebView原生跟JS交互功能的,github上的开源项目JSBridge就是采用这种方法: https://github.com/lzyzsd/JsBridge</p> <p>之前拜读过大名鼎鼎的cordova的源码,它内部的原生JS交互也是采用onJsPrompt的方式,不过在此基础上做了更强大的封装。</p> <hr> <p>###WebView后台耗电问题</p> <p>当我们的WebView的web页面在解析或者播放视频再或者有js定时器在执行的时, 如果我们把应用退到后台,不做任何处理的情况下,以上的操作还会在后台继续执行,导致WebView在后台持续耗电,因此一般我们会做以下处理</p> <pre><code lang="bash" class="hljs bash"> @Override protected void <span class="hljs-function"><span class="hljs-title">onPause</span></span>() { super.onPause(); mWebView.onPause();//暂停部分可安全处理的操作,如动画,定位,视频播放等 mWebView.pauseTimers();//暂停所有WebView的页面布局、解析以及JavaScript的定时器操作 } @Override protected void <span class="hljs-function"><span class="hljs-title">onResume</span></span>() { super.onResume(); mWebView.onResume(); mWebView.resumeTimers(); } </code></pre><hr> <p>对于WebView的使用,在处理问题的过程中发现一个不错的开源库: https://github.com/delight-im/Android-AdvancedWebView</p> <p>基本上上面我提到的或者没提到的问题它都做了一定的封装处理,并且考虑了一些版本适配的问题,可以直接拿来使用,也可以拿来参考学习。</p> <p>如果你觉得问题还是太多的话也可以考虑使用<a href="http://x5.tencent.com/" target="_blank">腾讯浏览服务</a>,基于QQ浏览器X5内核,适配了Android全部主流平台,可以在所有Android手机上使用Blink的技术能力,具有更好的H5/CSS3支持和性能,目前微信、qq都在使用它。</p> <p>唯一的缺陷就是它不提供打包内核版的SDK,第一次使用时,它会自动到腾讯服务端去下载内核,下载完毕后会弹窗提示用户是否重启app,重启之后就能正常使用x5浏览服务了,如果你不介意这样的用户体验,可以考虑直接使用腾讯浏览服务。</p> <hr> <p>(补充) ###WebView混淆问题</p> <p>如果app打包混淆之后发现提供给web页面的JS接口失效了,记得检查是否添加了JavaScriptInterface的混淆配置:</p> <pre><code lang="bash" class="hljs bash">-keepclassmembers class * { @android.webkit.JavascriptInterface <methods>; } </code></pre><p>###红米WebView内部Web页面的div自身滚动条问题 红米上WebView内部的Web页面的div由于内容高度大于div,产生了基于div的滚动条(WebView滚动条已禁用的情况下),通过设置div的css样式来禁用div滚动条</p> <pre><code lang="bash" class="hljs bash">Html dom元素ID或class:: -webkit-scrollbar {display:none} </code></pre><p>###WebView内部web页面px跟dp的关系 经测试发现,WebView内部web页面的px值会在内部自动转换为dp,且1px=1dp,跟ppi值无关,这点跟原生开发中的1dp = 设备ppi/160 * px换算关系nveou</p> </p> </div> </div> </div> </div> </div> </div> <!--PC和WAP自适应版--> <div id="SOHUCS" sid="1290061306619043840"></div> <script type="text/javascript" src="/views/front/js/chanyan.js"></script> <!-- 文章页-底部 动态广告位 --> <div class="youdao-fixed-ad" id="detail_ad_bottom"></div> </div> <div class="col-md-3"> <div class="row" id="ad"> <!-- 文章页-右侧1 动态广告位 --> <div id="right-1" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_1"> </div> </div> <!-- 文章页-右侧2 动态广告位 --> <div id="right-2" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_2"></div> </div> <!-- 文章页-右侧3 动态广告位 --> <div id="right-3" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_3"></div> </div> </div> </div> </div> </div> </div> <div class="container"> <h4 class="pt20 mb15 mt0 border-top">你可能感兴趣的:(Android爬坑之旅之WebView)</h4> <div id="paradigm-article-related"> <div class="recommend-post mb30"> <ul class="widget-links"> <li><a href="/article/1773611795592839168.htm" title="《昼颜》里的日本女人:相遇要万种风情,分手要残忍绝情" target="_blank">《昼颜》里的日本女人:相遇要万种风情,分手要残忍绝情</a> <span class="text-muted">迷影咖啡</span> <div>作者:迷之菌子神奇菇迷影咖啡:一本正经做烘焙,胡说八道聊电影漫天萤火虫消散之时良宵就将过去,人们也说含苞待放的花蕾总会开了又谢,因紧紧相拥而面红耳赤的躯体,便是我们经历过这热爱的证明。夫妻关系介绍《昼颜》是2014年电视剧《昼颜:工作日下午三点的恋人们》的续集,故事发在电视剧情节结束的三年后,讲述了已经恢复独身的纱和偶然与曾经的出轨对象北野重逢后再次陷入感情漩涡的故事。《昼颜》制作灵感源自利佳子在</div> </li> <li><a href="/article/1773611668312489984.htm" title="迎接2019" target="_blank">迎接2019</a> <span class="text-muted">唯有杜康1994</span> <div>告别2018这一年是机遇与挑战,痛苦与喜悦,失去与收获的一年一月:收获了第一份爱情,开始真正想去了解一个人三月:对工作有了更深入的认识,靠自己的力量完成晋升五月:搬家,住进了自己理想的公寓,一间属于自己的屋子。满地的书六月:外调广州,升经理,有了自己的第一个团队。七月:怀着自我否定,第一次完成了部门任务八月:第一个员工流失,痛哭不已明白无不散之筵席九月:员工陆续离开,经济是一切的根本。十月:陪员工</div> </li> <li><a href="/article/1773611163691581440.htm" title="亲子日记之祝姑姥姥生日快乐(282)" target="_blank">亲子日记之祝姑姥姥生日快乐(282)</a> <span class="text-muted">冰心雨露_d504</span> <div>2021年7月18日,周日,晴周日上班的不上班,上学的不上学,全家都属于休息状态,洗衣做饭是上午的主要任务,中午休息一会儿,下午比较晚了出去给梦怡买了二年级上册的口算题卡,然后去参加姑姑的生日聚餐,本来姑姑应该是周一生日,因为周一都要上班,就提前到周日过了,说是过生日其实就是想借此机会一家人聚聚,毕竟平常都忙,没有时间聚在一起,梦怡还给姑姥姥做了生日贺卡,虽然长相一般,重在心意。生日快乐</div> </li> <li><a href="/article/1773610251875057664.htm" title="Android和IOS应用开发-Flutter应用让屏幕在 app 运行期间保持常亮的方法" target="_blank">Android和IOS应用开发-Flutter应用让屏幕在 app 运行期间保持常亮的方法</a> <span class="text-muted">江上清风山间明月</span> <a class="tag" taget="_blank" href="/search/Flutter/1.htm">Flutter</a><a class="tag" taget="_blank" href="/search/android/1.htm">android</a><a class="tag" taget="_blank" href="/search/ios/1.htm">ios</a><a class="tag" taget="_blank" href="/search/flutter/1.htm">flutter</a><a class="tag" taget="_blank" href="/search/KeepAlive/1.htm">KeepAlive</a><a class="tag" taget="_blank" href="/search/%E5%B1%8F%E5%B9%95%E5%B8%B8%E4%BA%AE/1.htm">屏幕常亮</a><a class="tag" taget="_blank" href="/search/wakelock/1.htm">wakelock</a><a class="tag" taget="_blank" href="/search/%E7%86%84%E5%B1%8F/1.htm">熄屏</a> <div>文章目录Flutter应用让屏幕在app运行期间保持常亮的方法方法一:使用系统插件方法二:使用Widgets注意事项Flutter应用让屏幕在app运行期间保持常亮的方法在Flutter开发中,可以使用以下两种方法让屏幕在app运行期间保持常亮:方法一:使用系统插件Flutter社区中已经有很多相关插件可供使用,比如wakelock:https://pub.dev/packages/wakeloc</div> </li> <li><a href="/article/1773604712738783232.htm" title="android 自定义曲线图,Android自定义View——贝赛尔曲线" target="_blank">android 自定义曲线图,Android自定义View——贝赛尔曲线</a> <span class="text-muted">weixin_39767513</span> <a class="tag" taget="_blank" href="/search/android/1.htm">android</a><a class="tag" taget="_blank" href="/search/%E8%87%AA%E5%AE%9A%E4%B9%89%E6%9B%B2%E7%BA%BF%E5%9B%BE/1.htm">自定义曲线图</a> <div>个人博客:haichenyi.com。感谢关注本文针对有一定自定义View的童鞋,最好对贝赛尔曲线有辣么一丢丢了解,不了解也没关系。花5分钟看一下GcsSloop的安卓自定义View进阶-Path之贝塞尔曲线。本文的最终效果图:最终效果图.gif思路首先他是一个只有上半部分的正弦形状的水波纹,很规则。其次,他这个正弦图左右在移动。然后,就是它这个自定义View,上下也在移动,是慢慢增加的最后,优化</div> </li> <li><a href="/article/1773593758407917568.htm" title="Mac命令行查找SDK/JDK安装位置" target="_blank">Mac命令行查找SDK/JDK安装位置</a> <span class="text-muted">iblade</span> <a class="tag" taget="_blank" href="/search/Linux/1.htm">Linux</a><a class="tag" taget="_blank" href="/search/macos/1.htm">macos</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a> <div>要在命令行中查询AndroidSDKPlatformTools的安装位置,可以使用以下步骤:使用which命令:在命令行中执行以下命令:whichadb这将输出adb命令的安装路径,通常情况下,它会在AndroidSDK的platform-tools目录下。手动查找:如果whichadb没有输出,可以手动查找AndroidSDK的安装位置。通常情况下,AndroidSDK的默认安装路径是在用户的h</div> </li> <li><a href="/article/1773585584300818432.htm" title="下载Android源码" target="_blank">下载Android源码</a> <span class="text-muted">赛非斯</span> <div>repoinit-uhttps://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest-bandroid-10.0.0_r411.首先下载repo:a)终端运行gitclonegit://codeaurora.org/tools/repo.gitb)mkdir~/binc)拷贝repo到~/bin下面,修改repo权限,chmoda+x~</div> </li> <li><a href="/article/1773581925500387328.htm" title="信任" target="_blank">信任</a> <span class="text-muted">饮冰伊乔</span> <div>随着社会的发展,微信和支付宝交易给人们带来了极大的方便,越来越多的人出门都只选择拿一部手机即可,方便安全,可昨天我就遇到了一件比较尴尬的事。昨天傍晚,我从公司出来,感觉有点饿,决定索性吃了饭再回去,来到去过几次的一个店里,如往常一样叫了餐,当时店里吃饭的不多,老板麻利的先去做了,正要扫微信付账的时候发现手机没电了,迷之尴尬,我只好跟老板说不用做了,手机没电了,我身上又没现金,付不了帐了。老板娘很热</div> </li> <li><a href="/article/1773554866065571840.htm" title="Django之Debug篇" target="_blank">Django之Debug篇</a> <span class="text-muted">菜鸟之编程</span> <a class="tag" taget="_blank" href="/search/Django/1.htm">Django</a><a class="tag" taget="_blank" href="/search/django/1.htm">django</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a> <div>一、DebugToolBar基本使用1.1、概述Django框架的调试工具栏使用django-debug-toolbar库,是一组可配置的面板,显示有关当前请求/响应的各种调试信息,点击时,显示有关面板内容的更多详细信息。官方文档:DjangoDebugToolbar—DjangoDebugToolbar4.3.0documentation1.2、安装pipinstalldjango-debug-</div> </li> <li><a href="/article/1773515880156692480.htm" title="以高质量调查研究助力组织工作提质增效" target="_blank">以高质量调查研究助力组织工作提质增效</a> <span class="text-muted">木同木同</span> <div>近日,中共中央办公厅印发了《关于在全党大兴调查研究的工作方案》(后简称《方案》),要求各地区各部门结合实际认真贯彻落实。调查研究是我们党的传家宝,是谋事之基、成事之道。组织部门作为党管干部的核心部门,肩负着管党员、管干部、管人才的重要职责,调查研究更是把握组织工作规律、破解组织工作难题的重要办法。要用好调查研究这一法宝,把准政治方向,贯穿问题导向,坚持实事求是,以高质量调查研究助力组织工作提质增效</div> </li> <li><a href="/article/1773514618988199936.htm" title="地低为海人低为王" target="_blank">地低为海人低为王</a> <span class="text-muted">缘梦草</span> <div>地低为海,人低为王。低,高之基,高,低之顶。谦虚才能收益,咄咄逼人会招损。高粱熟了,头会低下。受益反而会深藏不露。捧人之术,把人捧高,然后控制。受控之人,大都是虚荣心作祟。活成别人想象中的样子,像别人想象中那么有面子的活着是悲哀的。穷不可怕,怕的是虚荣心。当你好面子,你就会被控制。一旦受虚荣心控制,你不得不谨小慎微的维护面子,付出多余的能量,希望得到别人的一句赞。面子就是金子打造的牢笼,让你在赞美</div> </li> <li><a href="/article/1773499744581124096.htm" title="计划比盲目做重要" target="_blank">计划比盲目做重要</a> <span class="text-muted">一祉微笑</span> <div>坚持分享第99天。一次次会议提醒着老师们假期余额不足,马上面临停机状态。50多天掐指而过,想想放假时的计划,对照如今的完成情况,感觉差太远。想着好好看书,如今50多天过去了第6本还处在未完待续状态;想着假期好好陪陪孩子,在玩中学一些知识,如今想想,孩子学的真不多;想着暑假坚持跑步,有时还是容易给自己找借口,休息三两天。给这个假期一个综合评价,只能说只完成了计划的百分之五六十。想想为什么临近开学没达</div> </li> <li><a href="/article/1773477172762181632.htm" title="081天 约柜失而复得" target="_blank">081天 约柜失而复得</a> <span class="text-muted">宁宁2018</span> <div>撒迦利亚书4:6他对我说:“这是耶和华指示所罗巴伯的。万军之耶和华说:‘不是倚靠势力,不是倚靠才能,乃是倚靠我的灵方能成事。’</div> </li> <li><a href="/article/1773468510236770304.htm" title="flutter 修改app名字和图标" target="_blank">flutter 修改app名字和图标</a> <span class="text-muted">肥肥呀呀呀</span> <a class="tag" taget="_blank" href="/search/flutter/1.htm">flutter</a> <div>一、修改名字在Android中修改应用程序名称:在AndroidManifest.xml文件中修改应用程序名称:打开Flutter项目中的android/app/src/main/AndroidManifest.xml文件。找到标签,然后在android:label属性中修改应用程序的名称,例如:android:label="YourNewAppName"。在strings.xml文件中修改应用程</div> </li> <li><a href="/article/1773468344071028736.htm" title="《金文成〈正蒙〉日记124。2020-11-9》" target="_blank">《金文成〈正蒙〉日记124。2020-11-9》</a> <span class="text-muted">金吾生</span> <div>《金文成〈正蒙〉日记124。2020-11-9》今天是庚子丁亥丙子,九月廿四,2020年11月9日星期一。作者篇7【舜之孝,汤、武之武,虽顺逆不同,其为不幸均矣。】船山讲解说,顺,指的是舜的父亲最终受到感化,转变了态度,结局圆满之事;逆,指的是"桀放、纣诛",即,商汤放桀,周武诛纣,都是采用暴力,不是感化方式,所以是逆。顺与逆,都是为了解决弊政,然其差异之大如此,然而,无论圆满还是遗憾,其实他们都</div> </li> <li><a href="/article/1773451453554294784.htm" title="如何把大象装进冰箱的思考 210624" target="_blank">如何把大象装进冰箱的思考 210624</a> <span class="text-muted">大丁_初心生活</span> <div>央视春晚曾有个小品,宋丹丹问赵本山,如何把大象装进冰箱。赵本山说不知道。宋丹丹得意地说,第一步,把冰箱门打开。第二步,把大象装进去。第三步,把冰箱门关上。我相信很多人看了都是一笑了之,我们也从潜意识上给出了否定的答案。樊登老师给出了不一样的解读,他认为这其实是解决问题的经典方法。“把大象装冰箱”,目标十分明确,宋丹丹给出的执行步骤也十分清晰。可赵本山却不会?难道赵本山不知道这三个步骤吗?肯定知道。</div> </li> <li><a href="/article/1773387157499609088.htm" title="道德经第三十四章" target="_blank">道德经第三十四章</a> <span class="text-muted">套马地汉纸</span> <div>道德经第三十四章原文:大道泛兮,其可左右!万物恃之而生,而不辞,功成不名有。爱养万物而不为主,常无欲,可名于小;万物归焉而不为主,可名为大。是以圣人终不为大,故能成其大。译文:大道广泛流行,无所不到。万物依赖它生长而不推辞,有所成就而不自以为有功。养育万物而不自以为主,永远没有私欲,可以说是渺小得很,所以可称它为“小”;物归附于它而它不自以为主宰,可以说极其伟大,所以可称它为“大”。由于它不自以为</div> </li> <li><a href="/article/1773377374927257600.htm" title="Linux学习系列之vim编辑器(一)" target="_blank">Linux学习系列之vim编辑器(一)</a> <span class="text-muted">llibertyll</span> <a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a> <div>vi编辑器的操作模式输入模式—aio等—>命令模式<—:键—末行模式从输入/末行模式切换到命令模式都是需要按ESC键注:a光标后输入,i光标前输入,o直接向下加一行输入,O向上加一行输入在vi编辑器中光标的移动(命令行模式下)键组合(命令)光标的移动$光标移动到当前行的结尾0(零)光标移动到当前行的开始GG光标移动到最后一行gg光标移动到第一行在命令行模式下删除与复制的操作键组合(命令)含义dd删</div> </li> <li><a href="/article/1773374180901847040.htm" title="6/21 最后的编织之观后感" target="_blank">6/21 最后的编织之观后感</a> <span class="text-muted">ChereAlicia</span> <div>今天看了7分钟震撼人心之短篇有种当局者迷旁观者清的感觉在外人眼里看来已经足够但自有人深陷其中无法自拔而那个人很有可能是自己超脱物质寻求自己真正想要的方能得到内心的平息和安宁图片发自App</div> </li> <li><a href="/article/1773367246526152704.htm" title="每天学点成语" target="_blank">每天学点成语</a> <span class="text-muted">余子烨</span> <div>1、口诀:功败垂成未成功,不以为然不赞同;火中取栗被利用,罚不当罪处罚重;2、解释:功败垂成:事情接近成功的时候却遭到了失败。出自:《三国志·杨阜传》:“弃垂成之功,陷不义之名,阜以死守之。”不以为然:不认为是对的。表示不同意或否定。出自:宋·苏轼《再乞罢详定役法状》:“右臣先曾奏论前衙一役,只当招募,不当定差,执政不以为然。”火中取栗:一只猴子和一只猫看见炉火中烤着栗子,猴子叫猫去偷,猫用爪子从</div> </li> <li><a href="/article/1773353080805457920.htm" title="Android 系统应用 pk8签名文件转jks或keystore教程" target="_blank">Android 系统应用 pk8签名文件转jks或keystore教程</a> <span class="text-muted">蜗牛、Z</span> <a class="tag" taget="_blank" href="/search/AOSP/1.htm">AOSP</a><a class="tag" taget="_blank" href="/search/android/1.htm">android</a><a class="tag" taget="_blank" href="/search/Framework/1.htm">Framework</a><a class="tag" taget="_blank" href="/search/android/1.htm">android</a><a class="tag" taget="_blank" href="/search/aosp/1.htm">aosp</a><a class="tag" taget="_blank" href="/search/%E7%B3%BB%E7%BB%9F%E5%BA%94%E7%94%A8%E5%BC%80%E5%8F%91/1.htm">系统应用开发</a> <div>一、介绍签名文件对于我们在做应用开发中,经常遇到,且签名文件不仅仅是保护应用安全,还会涉及到应用与底层之间的数据共享和API文件等问题。在Android中,签名文件同样也存在这个问题。但是android中又区分系统应用和普通应用。系统应用可以通过android:sharedUserId="android.uid.system"同享系统uid,可以获取更高的权限。所以在做系统应用开发的时候,经常需要</div> </li> <li><a href="/article/1773349852445474816.htm" title="2023-11-07" target="_blank">2023-11-07</a> <span class="text-muted">碎碎念念的每一天</span> <div>忽然开始自卑了,感觉自己无论各个方面都太平平,读书不多,家务做不好,体重控制的不好,早起也困难,起来又不知道该做什么,没有一个可以为之奋斗的目标,也没有很好的交际圈,感觉自己就像一只在笼子里的鸟,想飞也飞不高……我想改变这样的现状,可该如何呢?其实都是我不够努力,没有争分夺秒,没有自律,这些都是我未来跟人拉开差距的原因,所以,我不应该只是自卑,自卑过头会变成焦虑,我应该努力去改变,哪怕改变一小点,</div> </li> <li><a href="/article/1773342128299114496.htm" title="stm32之GPIO寄存器" target="_blank">stm32之GPIO寄存器</a> <span class="text-muted">luofengmacheng</span> <a class="tag" taget="_blank" href="/search/%E5%B5%8C%E5%85%A5%E5%BC%8F/1.htm">嵌入式</a><a class="tag" taget="_blank" href="/search/stm32/1.htm">stm32</a><a class="tag" taget="_blank" href="/search/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%A1%AC%E4%BB%B6/1.htm">嵌入式硬件</a><a class="tag" taget="_blank" href="/search/%E5%8D%95%E7%89%87%E6%9C%BA/1.htm">单片机</a> <div>文章目录1背景2GPIO寄存器的类型2.1端口配置寄存器2.2设置/清除寄存器和位清除寄存器3总结1背景C51单片机在进行数据的输入输出时,是直接操作与外部引脚关联的内部寄存器,例如,当设置P2_1为0时,就是将外部引脚的P21引脚设置为低电平,当读取P2_1时,就是读取P21的电平。与之类似,stm32芯片内部也有很多用于输入输出的寄存器,这些寄存器也是用于操作外部引脚,但是比C51单片机复杂很</div> </li> <li><a href="/article/1773340139582455808.htm" title="《老子》笔记19 2018-10-28" target="_blank">《老子》笔记19 2018-10-28</a> <span class="text-muted">海上明月共</span> <div>第二十二章[原文]曲则全,枉则直,洼则盈,敝则新,少则得,多则惑。是以圣人抱一为天下式。不自见,故明;不自是,故彰,不自伐,故有功;不自矜,故长。夫唯不争,故天下莫能与之争。古之所谓"曲则全"者,岂虚言哉?诚全而归之。[译文]委曲便会保全,屈枉便会直伸;低洼便会充盈,陈旧便会更新;少取便会获得,贪多便会迷惑。所以有道的人坚守这一原则作为天下事理的范式,不自我表扬,反能显明;不自以为是,反能是非彰明</div> </li> <li><a href="/article/1773338753864105984.htm" title="爱心账户之存钱日记11.20" target="_blank">爱心账户之存钱日记11.20</a> <span class="text-muted">静_d595</span> <div>新沙发终于到了,满心欢喜,可旧沙发的处理又是个头疼的问题,免费送都没有人要。临时想起来公司那个收垃圾的,看看付费能不能拉走。对方说随便给点都行,我又拿不准,于是就想说88把。对方说给两包烟就行了,我说还是给钱吧,也不想欠人情。如果请专门搬东西的估计得200加了,还算是比较顺利,刚好想到他。选了12元存进我的爱心账户!</div> </li> <li><a href="/article/1773256662182854656.htm" title="大话设计模式之工厂模式" target="_blank">大话设计模式之工厂模式</a> <span class="text-muted">码农客栈</span> <a class="tag" taget="_blank" href="/search/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/1.htm">设计模式</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a> <div>工厂模式(FactoryPattern)是一种创建型设计模式,它提供了一种创建对象的最佳方式,而无需指定将要创建的对象的确切类。通过使用工厂模式,我们可以将对象的创建和使用分离,从而使代码更具灵活性和可维护性。在工厂模式中,通常会有三种角色:工厂接口(FactoryInterface):声明了一个用于创建对象的接口,这样所有具体工厂类都必须实现该接口。具体工厂(ConcreteFactory):实</div> </li> <li><a href="/article/1773229094205456384.htm" title="ReactNative应用打包后无网络解决方案" target="_blank">ReactNative应用打包后无网络解决方案</a> <span class="text-muted">程序猿也会飞</span> <a class="tag" taget="_blank" href="/search/%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/1.htm">最佳实践</a><a class="tag" taget="_blank" href="/search/react/1.htm">react</a><a class="tag" taget="_blank" href="/search/native/1.htm">native</a><a class="tag" taget="_blank" href="/search/android/1.htm">android</a><a class="tag" taget="_blank" href="/search/react.js/1.htm">react.js</a> <div>ReactNative打包应用后,应用没有网络解决方案:在android\app\src\main\res下创建xml文件夹在xml文件夹中创建network_security_config.xml文件network_security_config.xml内容:在android\app\src\main文件夹AndroidManifest.xml文件内的Application标签中添加属性andr</div> </li> <li><a href="/article/1773162507913986048.htm" title="git使用代理解决无法clone的问题及git代理设置" target="_blank">git使用代理解决无法clone的问题及git代理设置</a> <span class="text-muted">yaningli</span> <div>在使用git的时候,经常需要去国外的一些网站clone,由于众所周知的原因,clone失败例如:$gitclonehttps://android.googlesource.com/platform/packages/apps/MessagingCloninginto‘Messaging’…fatal:unabletoaccess‘https://android.googlesource.com/p</div> </li> <li><a href="/article/1772792265987653632.htm" title="大话设计模式之代理模式" target="_blank">大话设计模式之代理模式</a> <span class="text-muted">码农客栈</span> <a class="tag" taget="_blank" href="/search/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/1.htm">设计模式</a><a class="tag" taget="_blank" href="/search/%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F/1.htm">代理模式</a> <div>代理模式(ProxyPattern)是一种结构型设计模式,它允许通过代理对象控制对另一个对象的访问。代理对象充当客户端和实际对象之间的中介,客户端通过代理对象间接访问实际对象,从而可以在访问控制、缓存、延迟加载等方面提供额外的功能。在代理模式中,通常会有三种角色:Subject(抽象主题):声明了真实对象和代理对象的共同接口,这样在任何使用真实对象的地方都可以使用代理对象。RealSubject(</div> </li> <li><a href="/article/1772789495305928704.htm" title="【1.1 编程基础之输入输出】09. 字符菱形" target="_blank">【1.1 编程基础之输入输出】09. 字符菱形</a> <span class="text-muted">青少年编程小助手_Python</span> <a class="tag" taget="_blank" href="/search/Openjudge%E9%A2%98%E7%9B%AE%E8%A7%A3%E6%9E%90/1.htm">Openjudge题目解析</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E9%9D%92%E5%B0%91%E5%B9%B4%E7%BC%96%E7%A8%8B/1.htm">青少年编程</a><a class="tag" taget="_blank" href="/search/%E7%94%B5%E5%AD%90%E5%AD%A6%E4%BC%9A/1.htm">电子学会</a><a class="tag" taget="_blank" href="/search/%E7%AD%89%E7%BA%A7%E8%80%83%E8%AF%95/1.htm">等级考试</a><a class="tag" taget="_blank" href="/search/gesp/1.htm">gesp</a> <div>09:字符菱形总时间限制:1000ms内存限制:65536kB描述给定一个字符,用它构造一个对角线长5个字符,倾斜放置的菱形。输入输入只有一行,包含一个字符。输出该字符构成的菱形。样例输入*样例输出*************参考程序(1)C语言#includeintmain(){charc;scanf("%c",&c);printf("%c\n",c);printf("%c%c%c\n",c,c,</div> </li> <li><a href="/article/87.htm" title="面向对象面向过程" target="_blank">面向对象面向过程</a> <span class="text-muted">3213213333332132</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>面向对象:把要完成的一件事,通过对象间的协作实现。 面向过程:把要完成的一件事,通过循序依次调用各个模块实现。 我把大象装进冰箱这件事为例,用面向对象和面向过程实现,都是用java代码完成。 1、面向对象 package bigDemo.ObjectOriented; /** * 大象类 * * @Description * @author FuJian</div> </li> <li><a href="/article/214.htm" title="Java Hotspot: Remove the Permanent Generation" target="_blank">Java Hotspot: Remove the Permanent Generation</a> <span class="text-muted">bookjovi</span> <a class="tag" taget="_blank" href="/search/HotSpot/1.htm">HotSpot</a> <div>  openjdk上关于hotspot将移除永久带的描述非常详细,http://openjdk.java.net/jeps/122   JEP 122: Remove the Permanent Generation Author Jon Masamitsu Organization Oracle Created 2010/8/15 Updated 2011/</div> </li> <li><a href="/article/341.htm" title="正则表达式向前查找向后查找,环绕或零宽断言" target="_blank">正则表达式向前查找向后查找,环绕或零宽断言</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F/1.htm">正则表达式</a> <div>向前查找和向后查找 1. 向前查找:根据要匹配的字符序列后面存在一个特定的字符序列(肯定式向前查找)或不存在一个特定的序列(否定式向前查找)来决定是否匹配。.NET将向前查找称之为零宽度向前查找断言。     对于向前查找,出现在指定项之后的字符序列不会被正则表达式引擎返回。 2. 向后查找:一个要匹配的字符序列前面有或者没有指定的</div> </li> <li><a href="/article/468.htm" title="BaseDao" target="_blank">BaseDao</a> <span class="text-muted">171815164</span> <a class="tag" taget="_blank" href="/search/seda/1.htm">seda</a> <div> import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.PreparedStatement; import java.sql.ResultSet; public class BaseDao { public Conn</div> </li> <li><a href="/article/595.htm" title="Ant标签详解--Java命令" target="_blank">Ant标签详解--Java命令</a> <span class="text-muted">g21121</span> <a class="tag" taget="_blank" href="/search/Java%E5%91%BD%E4%BB%A4/1.htm">Java命令</a> <div>        这一篇主要介绍与java相关标签的使用         终于开始重头戏了,Java部分是我们关注的重点也是项目中用处最多的部分。           1</div> </li> <li><a href="/article/722.htm" title="[简单]代码片段_电梯数字排列" target="_blank">[简单]代码片段_电梯数字排列</a> <span class="text-muted">53873039oycg</span> <a class="tag" taget="_blank" href="/search/%E4%BB%A3%E7%A0%81/1.htm">代码</a> <div>       今天看电梯数字排列是9 18 26这样呈倒N排列的,写了个类似的打印例子,如下:       import java.util.Arrays; public class 电梯数字排列_S3_Test { public static void main(S</div> </li> <li><a href="/article/849.htm" title="Hessian原理" target="_blank">Hessian原理</a> <span class="text-muted">云端月影</span> <a class="tag" taget="_blank" href="/search/hessian%E5%8E%9F%E7%90%86/1.htm">hessian原理</a> <div>Hessian 原理分析 一.      远程通讯协议的基本原理 网络通信需要做的就是将流从一台计算机传输到另外一台计算机,基于传输协议和网络 IO 来实现,其中传输协议比较出名的有 http 、 tcp 、 udp 等等, http 、 tcp 、 udp 都是在基于 Socket 概念上为某类应用场景而扩展出的传输协</div> </li> <li><a href="/article/976.htm" title="区分Activity的四种加载模式----以及Intent的setFlags" target="_blank">区分Activity的四种加载模式----以及Intent的setFlags</a> <span class="text-muted">aijuans</span> <a class="tag" taget="_blank" href="/search/android/1.htm">android</a> <div>  在多Activity开发中,有可能是自己应用之间的Activity跳转,或者夹带其他应用的可复用Activity。可能会希望跳转到原来某个Activity实例,而不是产生大量重复的Activity。 这需要为Activity配置特定的加载模式,而不是使用默认的加载模式。 加载模式分类及在哪里配置 Activity有四种加载模式: standard singleTop</div> </li> <li><a href="/article/1103.htm" title="hibernate几个核心API及其查询分析" target="_blank">hibernate几个核心API及其查询分析</a> <span class="text-muted">antonyup_2006</span> <a class="tag" taget="_blank" href="/search/html/1.htm">html</a><a class="tag" taget="_blank" href="/search/.net/1.htm">.net</a><a class="tag" taget="_blank" href="/search/Hibernate/1.htm">Hibernate</a><a class="tag" taget="_blank" href="/search/xml/1.htm">xml</a><a class="tag" taget="_blank" href="/search/%E9%85%8D%E7%BD%AE%E7%AE%A1%E7%90%86/1.htm">配置管理</a> <div>(一)  org.hibernate.cfg.Configuration类         读取配置文件并创建唯一的SessionFactory对象.(一般,程序初始化hibernate时创建.)         Configuration co</div> </li> <li><a href="/article/1230.htm" title="PL/SQL的流程控制" target="_blank">PL/SQL的流程控制</a> <span class="text-muted">百合不是茶</span> <a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a><a class="tag" taget="_blank" href="/search/PL%2FSQL%E7%BC%96%E7%A8%8B/1.htm">PL/SQL编程</a><a class="tag" taget="_blank" href="/search/%E5%BE%AA%E7%8E%AF%E6%8E%A7%E5%88%B6/1.htm">循环控制</a> <div>PL/SQL也是一门高级语言,所以流程控制是必须要有的,oracle数据库的pl/sql比sqlserver数据库要难,很多pl/sql中有的sqlserver里面没有   流程控制; 分支语句 if 条件 then 结果 else 结果 end if ; 条件语句 case when 条件 then 结果; 循环语句 loop </div> </li> <li><a href="/article/1357.htm" title="强大的Mockito测试框架" target="_blank">强大的Mockito测试框架</a> <span class="text-muted">bijian1013</span> <a class="tag" taget="_blank" href="/search/mockito/1.htm">mockito</a><a class="tag" taget="_blank" href="/search/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95/1.htm">单元测试</a> <div>一.自动生成Mock类        在需要Mock的属性上标记@Mock注解,然后@RunWith中配置Mockito的TestRunner或者在setUp()方法中显示调用MockitoAnnotations.initMocks(this);生成Mock类即可。二.自动注入Mock类到被测试类  &nbs</div> </li> <li><a href="/article/1484.htm" title="精通Oracle10编程SQL(11)开发子程序" target="_blank">精通Oracle10编程SQL(11)开发子程序</a> <span class="text-muted">bijian1013</span> <a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">数据库</a><a class="tag" taget="_blank" href="/search/plsql/1.htm">plsql</a> <div>/* *开发子程序 */ --子程序目是指被命名的PL/SQL块,这种块可以带有参数,可以在不同应用程序中多次调用 --PL/SQL有两种类型的子程序:过程和函数 --开发过程 --建立过程:不带任何参数 CREATE OR REPLACE PROCEDURE out_time IS BEGIN DBMS_OUTPUT.put_line(systimestamp); E</div> </li> <li><a href="/article/1611.htm" title="【EhCache一】EhCache版Hello World" target="_blank">【EhCache一】EhCache版Hello World</a> <span class="text-muted">bit1129</span> <a class="tag" taget="_blank" href="/search/Hello+world/1.htm">Hello world</a> <div>本篇是EhCache系列的第一篇,总体介绍使用EhCache缓存进行CRUD的API的基本使用,更细节的内容包括EhCache源代码和设计、实现原理在接下来的文章中进行介绍   环境准备 1.新建Maven项目   2.添加EhCache的Maven依赖 <dependency> <groupId>ne</div> </li> <li><a href="/article/1738.htm" title="学习EJB3基础知识笔记" target="_blank">学习EJB3基础知识笔记</a> <span class="text-muted">白糖_</span> <a class="tag" taget="_blank" href="/search/bean/1.htm">bean</a><a class="tag" taget="_blank" href="/search/Hibernate/1.htm">Hibernate</a><a class="tag" taget="_blank" href="/search/jboss/1.htm">jboss</a><a class="tag" taget="_blank" href="/search/webservice/1.htm">webservice</a><a class="tag" taget="_blank" href="/search/ejb/1.htm">ejb</a> <div>最近项目进入系统测试阶段,全赖袁大虾领导有力,保持一周零bug记录,这也让自己腾出不少时间补充知识。花了两天时间把“传智播客EJB3.0”看完了,EJB基本的知识也有些了解,在这记录下EJB的部分知识,以供自己以后复习使用。   EJB是sun的服务器端组件模型,最大的用处是部署分布式应用程序。EJB (Enterprise JavaBean)是J2EE的一部分,定义了一个用于开发基</div> </li> <li><a href="/article/1865.htm" title="angular.bootstrap" target="_blank">angular.bootstrap</a> <span class="text-muted">boyitech</span> <a class="tag" taget="_blank" href="/search/AngularJS/1.htm">AngularJS</a><a class="tag" taget="_blank" href="/search/AngularJS+API/1.htm">AngularJS API</a><a class="tag" taget="_blank" href="/search/angular%E4%B8%AD%E6%96%87api/1.htm">angular中文api</a> <div>angular.bootstrap 描述:     手动初始化angular。     这个函数会自动检测创建的module有没有被加载多次,如果有则会在浏览器的控制台打出警告日志,并且不会再次加载。这样可以避免在程序运行过程中许多奇怪的问题发生。   使用方法:     angular .</div> </li> <li><a href="/article/1992.htm" title="java-谷歌面试题-给定一个固定长度的数组,将递增整数序列写入这个数组。当写到数组尾部时,返回数组开始重新写,并覆盖先前写过的数" target="_blank">java-谷歌面试题-给定一个固定长度的数组,将递增整数序列写入这个数组。当写到数组尾部时,返回数组开始重新写,并覆盖先前写过的数</a> <span class="text-muted">bylijinnan</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div> public class SearchInShiftedArray { /** * 题目:给定一个固定长度的数组,将递增整数序列写入这个数组。当写到数组尾部时,返回数组开始重新写,并覆盖先前写过的数。 * 请在这个特殊数组中找出给定的整数。 * 解答: * 其实就是“旋转数组”。旋转数组的最小元素见http://bylijinnan.iteye.com/bl</div> </li> <li><a href="/article/2119.htm" title="天使还是魔鬼?都是我们制造" target="_blank">天使还是魔鬼?都是我们制造</a> <span class="text-muted">ducklsl</span> <a class="tag" taget="_blank" href="/search/%E7%94%9F%E6%B4%BB/1.htm">生活</a><a class="tag" taget="_blank" href="/search/%E6%95%99%E8%82%B2/1.htm">教育</a><a class="tag" taget="_blank" href="/search/%E6%83%85%E6%84%9F/1.htm">情感</a> <div>----------------------------剧透请原谅,有兴趣的朋友可以自己看看电影,互相讨论哦!!!     从厦门回来的动车上,无意中瞟到了书中推荐的几部关于儿童的电影。当然,这几部电影可能会另大家失望,并不是类似小鬼当家的电影,而是关于“坏小孩”的电影!     自己挑了两部先看了看,但是发现看完之后,心里久久不能平</div> </li> <li><a href="/article/2246.htm" title="[机器智能与生物]研究生物智能的问题" target="_blank">[机器智能与生物]研究生物智能的问题</a> <span class="text-muted">comsci</span> <a class="tag" taget="_blank" href="/search/%E7%94%9F%E7%89%A9/1.htm">生物</a> <div>       我想,人的神经网络和苍蝇的神经网络,并没有本质的区别...就是大规模拓扑系统和中小规模拓扑分析的区别....       但是,如果去研究活体人类的神经网络和脑系统,可能会受到一些法律和道德方面的限制,而且研究结果也不一定可靠,那么希望从事生物神经网络研究的朋友,不如把</div> </li> <li><a href="/article/2373.htm" title="获取Android Device的信息" target="_blank">获取Android Device的信息</a> <span class="text-muted">dai_lm</span> <a class="tag" taget="_blank" href="/search/android/1.htm">android</a> <div> String phoneInfo = "PRODUCT: " + android.os.Build.PRODUCT; phoneInfo += ", CPU_ABI: " + android.os.Build.CPU_ABI; phoneInfo += ", TAGS: " + android.os.Build.TAGS; ph</div> </li> <li><a href="/article/2500.htm" title="最佳字符串匹配算法(Damerau-Levenshtein距离算法)的Java实现" target="_blank">最佳字符串匹配算法(Damerau-Levenshtein距离算法)的Java实现</a> <span class="text-muted">datamachine</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8C%B9%E9%85%8D/1.htm">字符串匹配</a> <div>原文:http://www.javacodegeeks.com/2013/11/java-implementation-of-optimal-string-alignment.html------------------------------------------------------------------------------------------------------------</div> </li> <li><a href="/article/2627.htm" title="小学5年级英语单词背诵第一课" target="_blank">小学5年级英语单词背诵第一课</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/english/1.htm">english</a><a class="tag" taget="_blank" href="/search/word/1.htm">word</a> <div>long 长的 show 给...看,出示 mouth 口,嘴 write 写   use 用,使用 take 拿,带来 hand 手 clever 聪明的   often 经常 wash 洗 slow 慢的 house 房子   water 水 clean 清洁的 supper 晚餐 out 在外   face 脸,</div> </li> <li><a href="/article/2754.htm" title="macvim的使用实战" target="_blank">macvim的使用实战</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/mac/1.htm">mac</a><a class="tag" taget="_blank" href="/search/vim/1.htm">vim</a> <div>macvim用的是mac里面的vim, 只不过是一个GUI的APP, 相当于一个壳   1. 下载macvim https://code.google.com/p/macvim/   2. 了解macvim :h               vim的使用帮助信息 :h macvim  </div> </li> <li><a href="/article/2881.htm" title="java二分法查找" target="_blank">java二分法查找</a> <span class="text-muted">蕃薯耀</span> <a class="tag" taget="_blank" href="/search/java%E4%BA%8C%E5%88%86%E6%B3%95%E6%9F%A5%E6%89%BE/1.htm">java二分法查找</a><a class="tag" taget="_blank" href="/search/%E4%BA%8C%E5%88%86%E6%B3%95/1.htm">二分法</a><a class="tag" taget="_blank" href="/search/java%E4%BA%8C%E5%88%86%E6%B3%95/1.htm">java二分法</a> <div>java二分法查找 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 蕃薯耀 2015年6月23日 11:40:03 星期二 http:/</div> </li> <li><a href="/article/3008.htm" title="Spring Cache注解+Memcached" target="_blank">Spring Cache注解+Memcached</a> <span class="text-muted">hanqunfeng</span> <a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/memcached/1.htm">memcached</a> <div>Spring3.1 Cache注解  依赖jar包: <!-- simple-spring-memcached --> <dependency> <groupId>com.google.code.simple-spring-memcached</groupId> <artifactId>simple-s</div> </li> <li><a href="/article/3135.htm" title="apache commons io包快速入门" target="_blank">apache commons io包快速入门</a> <span class="text-muted">jackyrong</span> <a class="tag" taget="_blank" href="/search/apache+commons/1.htm">apache commons</a> <div>原文参考 http://www.javacodegeeks.com/2014/10/apache-commons-io-tutorial.html   Apache Commons IO 包绝对是好东西,地址在http://commons.apache.org/proper/commons-io/,下面用例子分别介绍:   1)  工具类   2</div> </li> <li><a href="/article/3262.htm" title="如何学习编程" target="_blank">如何学习编程</a> <span class="text-muted">lampcy</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E7%BC%96%E7%A8%8B/1.htm">编程</a><a class="tag" taget="_blank" href="/search/C%2B%2B/1.htm">C++</a><a class="tag" taget="_blank" href="/search/c/1.htm">c</a> <div>首先,我想说一下学习思想.学编程其实跟网络游戏有着类似的效果.开始的时候,你会对那些代码,函数等产生很大的兴趣,尤其是刚接触编程的人,刚学习第一种语言的人.可是,当你一步步深入的时候,你会发现你没有了以前那种斗志.就好象你在玩韩国泡菜网游似的,玩到一定程度,每天就是练级练级,完全是一个想冲到高级别的意志力在支持着你.而学编程就更难了,学了两个月后,总是觉得你好象全都学会了,却又什么都做不了,又没有</div> </li> <li><a href="/article/3389.htm" title="架构师之spring-----spring3.0新特性的bean加载控制@DependsOn和@Lazy" target="_blank">架构师之spring-----spring3.0新特性的bean加载控制@DependsOn和@Lazy</a> <span class="text-muted">nannan408</span> <a class="tag" taget="_blank" href="/search/Spring3/1.htm">Spring3</a> <div>1.前言。    如题。 2.描述。    @DependsOn用于强制初始化其他Bean。可以修饰Bean类或方法,使用该Annotation时可以指定一个字符串数组作为参数,每个数组元素对应于一个强制初始化的Bean。 @DependsOn({"steelAxe","abc"}) @Comp</div> </li> <li><a href="/article/3516.htm" title="Spring4+quartz2的配置和代码方式调度" target="_blank">Spring4+quartz2的配置和代码方式调度</a> <span class="text-muted">Everyday都不同</span> <a class="tag" taget="_blank" href="/search/%E4%BB%A3%E7%A0%81/1.htm">代码</a><a class="tag" taget="_blank" href="/search/%E9%85%8D%E7%BD%AE/1.htm">配置</a><a class="tag" taget="_blank" href="/search/spring4/1.htm">spring4</a><a class="tag" taget="_blank" href="/search/quartz2.x/1.htm">quartz2.x</a><a class="tag" taget="_blank" href="/search/%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1/1.htm">定时任务</a> <div>前言:这些天简直被quartz虐哭。。因为quartz 2.x版本相比quartz1.x版本的API改动太多,所以,只好自己去查阅底层API……   quartz定时任务必须搞清楚几个概念: JobDetail——处理类 Trigger——触发器,指定触发时间,必须要有JobDetail属性,即触发对象 Scheduler——调度器,组织处理类和触发器,配置方式一般只需指定触发</div> </li> <li><a href="/article/3643.htm" title="Hibernate入门" target="_blank">Hibernate入门</a> <span class="text-muted">tntxia</span> <a class="tag" taget="_blank" href="/search/Hibernate/1.htm">Hibernate</a> <div>  前言   使用面向对象的语言和关系型的数据库,开发起来很繁琐,费时。由于现在流行的数据库都不面向对象。Hibernate 是一个Java的ORM(Object/Relational Mapping)解决方案。   Hibernte不仅关心把Java对象对应到数据库的表中,而且提供了请求和检索的方法。简化了手工进行JDBC操作的流程。   如</div> </li> <li><a href="/article/3770.htm" title="Math类" target="_blank">Math类</a> <span class="text-muted">xiaoxing598</span> <a class="tag" taget="_blank" href="/search/Math/1.htm">Math</a> <div>一、Java中的数字(Math)类是final类,不可继承。 1、常数 PI:double圆周率 E:double自然对数 2、截取(注意方法的返回类型) double ceil(double d) 返回不小于d的最小整数 double floor(double d) 返回不大于d的整最大数 int round(float f) 返回四舍五入后的整数 long round</div> </li> </ul> </div> </div> </div> <div> <div class="container"> <div class="indexes"> <strong>按字母分类:</strong> <a href="/tags/A/1.htm" target="_blank">A</a><a href="/tags/B/1.htm" target="_blank">B</a><a href="/tags/C/1.htm" target="_blank">C</a><a href="/tags/D/1.htm" target="_blank">D</a><a href="/tags/E/1.htm" target="_blank">E</a><a href="/tags/F/1.htm" target="_blank">F</a><a href="/tags/G/1.htm" target="_blank">G</a><a href="/tags/H/1.htm" target="_blank">H</a><a href="/tags/I/1.htm" target="_blank">I</a><a href="/tags/J/1.htm" target="_blank">J</a><a href="/tags/K/1.htm" target="_blank">K</a><a href="/tags/L/1.htm" target="_blank">L</a><a href="/tags/M/1.htm" target="_blank">M</a><a href="/tags/N/1.htm" target="_blank">N</a><a href="/tags/O/1.htm" target="_blank">O</a><a href="/tags/P/1.htm" target="_blank">P</a><a href="/tags/Q/1.htm" target="_blank">Q</a><a href="/tags/R/1.htm" target="_blank">R</a><a href="/tags/S/1.htm" target="_blank">S</a><a href="/tags/T/1.htm" target="_blank">T</a><a href="/tags/U/1.htm" target="_blank">U</a><a href="/tags/V/1.htm" target="_blank">V</a><a href="/tags/W/1.htm" target="_blank">W</a><a href="/tags/X/1.htm" target="_blank">X</a><a href="/tags/Y/1.htm" target="_blank">Y</a><a href="/tags/Z/1.htm" target="_blank">Z</a><a href="/tags/0/1.htm" target="_blank">其他</a> </div> </div> </div> <footer id="footer" class="mb30 mt30"> <div class="container"> <div class="footBglm"> <a target="_blank" href="/">首页</a> - <a target="_blank" href="/custom/about.htm">关于我们</a> - <a target="_blank" href="/search/Java/1.htm">站内搜索</a> - <a target="_blank" href="/sitemap.txt">Sitemap</a> - <a target="_blank" href="/custom/delete.htm">侵权投诉</a> </div> <div class="copyright">版权所有 IT知识库 CopyRight © 2000-2050 E-COM-NET.COM , All Rights Reserved. <!-- <a href="https://beian.miit.gov.cn/" rel="nofollow" target="_blank">京ICP备09083238号</a><br>--> </div> </div> </footer> <!-- 代码高亮 --> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shCore.js"></script> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shLegacy.js"></script> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shAutoloader.js"></script> <link type="text/css" rel="stylesheet" href="/static/syntaxhighlighter/styles/shCoreDefault.css"/> <script type="text/javascript" src="/static/syntaxhighlighter/src/my_start_1.js"></script> </body> </html>