安卓WebView速度慢

188

我的 android webviews 很慢。这个问题出现在从手机到3.0+型号的平板电脑上,这些设备都有足够的规格。

我知道 webviews 应该是“有限制”的,但我看到通过 phone gap 完成的 web apps 必须使用各种 CSS3JQuery 的技巧,它们运行得非常好和迅速。

所以我想肯定缺少了一些东西,是否有一种类似于 myWebview.SPEEDHACK(1) 的方法可以用来加速呢?

此外,有时候我的 webview 内容就是根本不会加载,而不是缓慢加载。我正在测试的资源是本地存储的,没有错误。


3
似乎您需要发布一些代码。 - Jasoneer
1
可能是Android WebView性能的重复问题。 - Ken White
1
除了这个问题有更多的答案,这个问题有更好、更全面的答案,这个问题有两倍的浏览量,这两个问题都超过两年了,这些问题所涉及的安卓版本已经过时...你在标记这个问题时到底得到了什么? - CQM
@CQM:该问题因George Mays的重复答案而被系统自动标记。如果他的答案可以逐字逐句地重复作为多个帖子的答案,则其中一个是另一个的重复。链接的问题基于发布日期首先发布(并回答)。重复是重复的,第一篇帖子是原始帖子(回答也更早)。我没有从中获得任何好处(一开始也没有)。 - Ken White
1
此外,在您的应用程序中不要使用click事件,因为它会在每次单击时添加300毫秒的延迟来确定它是单击。最好使用touchstart代替。我已经创建了一个clickhandler,它使用两个事件并采用第一个触发的事件。我使用'touchstart click',所以它也可以在没有触摸屏的情况下正常工作。 - Codebeat
11个回答

142

这取决于正在加载的Web应用程序。尝试以下一些方法:

设置更高的渲染优先级(从API 18+已弃用):

webview.getSettings().setRenderPriority(RenderPriority.HIGH);

启用/禁用硬件加速:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    // chromium, enable hardware acceleration
    webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
} else {
    // older android version, disable hardware acceleration
    webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}

禁用缓存(如果您的内容存在问题):

webview.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);

49
我了解将渲染优先级设置为高会使其更快,但为什么要关闭缓存? - Dimas Kotvan
44
方法setRenderPriority已经过时,请参考http://developer.android.com/reference/android/webkit/WebSettings.html。 - Victor Ionescu
6
设置 setRenderPriority 的正确链接在这里 - Christopher Perry
7
为什么你要关闭缓存? - Hassy31
3
安卓存在一些神奇的问题,因此需要神奇的解决方案来拯救! - peceps
显示剩余8条评论

57

1
仅适用于API v11 / Android 3.x及更高版本。 - Ludwo
6
注意,根据问题https://dev59.com/mWQn5IYBdhLWcg3wJ0UO中所述,存在与硬件加速的WebViews相关的漏洞。请注意处理。 - Victor Ionescu
1
我注意到关闭硬件加速后,我的应用程序实际上更快。使用android:hardwareAccelerated="true" CSS 3D动画启动前会有很长的延迟,内部可滚动DIV元素的滚动不起作用,并且应用程序更加不稳定。 - Ernests Karlsons
3
如果您将minSdkVersion或targetSdkVersion设置为“14”或更高版本,则默认值为“true”。 - Vihaan Verma

38

我们的解决方案与此相反。我们使用以下代码仅在WebView上禁用硬件加速(而不是在清单文件中禁用整个应用程序):

if (Build.VERSION.SDK_INT >= 11){
    webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}

CSS3动画现在更加流畅。我们正在使用Android 4.0。

更多信息请参见:https://code.google.com/p/android/issues/detail?id=17352


5
很不幸,这也阻止了HTML5视频组件的工作 =/ - Ja͢ck
没有注意到。我们使用了视频视图来播放视频:幸运的是,我们只需要一个全屏视频。作为一种解决方法,可以让Webview透明并在后台播放视频视图,尽管我知道这不是同样的东西。 - Ena
1
这个修复方案还存在另一个问题。当触摸webview时,图形会有点失真。例如,如果您有一个带有圆形的图像,您会注意到它上面有小方块(像素),而不是平滑的线条。我可以告诉你,在Android 4.3上,这个修复方案是无用的,因为它没有性能问题。 - Ena
1
添加后,出现以下错误 WebView 未显示,因为它太大而无法适应软件层(或绘图缓存),需要 11534400 字节,但只有 8294400 可用 - Abc.Xyz
1
六年后...这仍然是对我有效的方法。 - chitgoks
显示剩余3条评论

14

我认为以下方案最好:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
} else {
    webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}

Android 19使用Chromium引擎作为WebView内核。我猜它在硬件加速方面的表现会更好。


2
这对于在动画和滚动效果不佳的WebViews上运行的我非常有效。 - cal
你的 "else" 和你的 "if" 是不是做了同样的事情? - Codebeat
Erwinus一种是针对type_SOFTWARE,另一种是针对Hardware。 - user2582318

10

我尝试了所有提议来解决我的Phonegap应用程序的渲染性能问题。但是没有什么真正起作用。

最终,在经过一整天的搜索后,我做到了。我在AndroidManifest的标签内(而不是标签外)设置了

<application android:hardwareAccelerated="false" ...

现在这个应用程序的表现和我的网页浏览器一样快。似乎硬件加速并不总是最好的功能...

我遇到的详细问题请参考:https://dev59.com/umPVa4cB1Zd3GeqP3zwl#24467920


3
禁用硬件加速对我来说效果很差,WebView 滚动非常缓慢。 - AbdelHady

9
我曾经遇到了同样的问题,我不得不解决它。我尝试了这些解决方案,但最终表现,至少对于滚动来说,没有任何改善。所以这里是我执行的解决方法以及为什么它对我有用的解释。
如果您有机会探索拖动事件,只需要创建一个“MiWebView”类,覆盖“onTouchEvent”方法并至少打印每个拖动事件发生的时间,您将看到它们的时间间隔为(向下)9毫秒。这是事件之间非常短的时间。
查看WebView源代码,只需查看onTouchEvent函数即可。处理器不可能在不到9ms的时间内处理它(继续做梦!!!)。这就是为什么您会不断看到“错过了拖动,因为我们正在等待WebCore响应触摸下降。”消息。代码无法按时处理。
如何修复它?首先,您不能重新编写onTouchEvent代码以改进它,因为它实在太多了。但是,您可以“模仿它”,以限制拖动运动的事件速率,比如说40ms或50ms。(这取决于处理器)。
所有触摸事件都是这样的:ACTION_DOWN-> ACTION_MOVE ...... ACTION_MOVE-> ACTION_UP。因此,我们需要保留DOWN和UP运动,并过滤MOVE速率(这些是坏家伙)。
这里是一种做法(您可以添加更多的事件类型,如2个手指的触摸,我在这里只关心单指滚动)。
import android.content.Context;
import android.view.MotionEvent;
import android.webkit.WebView;


public class MyWebView extends WebView{

    public MyWebView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }

    private long lastMoveEventTime = -1;
    private int eventTimeInterval = 40;

    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        long eventTime = ev.getEventTime();
        int action = ev.getAction();

        switch (action){
            case MotionEvent.ACTION_MOVE: {
                if ((eventTime - lastMoveEventTime) > eventTimeInterval){
                    lastMoveEventTime = eventTime;
                    return super.onTouchEvent(ev);
                }
                break;
            }
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_UP: {
                return super.onTouchEvent(ev);
            }
        }
        return true;
    }
}

当然,使用这个类来代替WebView,在滚动时你会看到差别。

这只是一种解决方案的方法,但由于在使用WebView时屏幕触摸会出现卡顿的情况,因此它并没有完全实现所有的滞后情况。然而,至少对于我的特定需求来说,这是我找到的最佳解决方案。


我想指出你发布的webview源代码是2010年的。 - CQM
这不起作用,它没有平滑滚动,我感觉不到任何区别。 - neevek
我已经将限制设置为80,但实际上似乎并没有改善性能,但它确实捕获了一些移动事件。对你有什么作用? - Ragnar
据了解,点击事件比触摸事件touchstart慢6倍。为避免延迟,您可以使用$('#button').on('touchstart click', function() { action here; return false; });。 - Codebeat
此外,在您的HTML应用程序中不要使用click事件,因为它会在每次单击时添加300毫秒的延迟来确定它是一个单击。最好使用touchstart代替。我已经创建了一个clickhandler,它使用两个事件并采用第一个触发的事件。我使用'touchstart click',所以即使没有触摸屏仍然可以正常工作。 - Codebeat
我尝试过这个,但奇怪的是,在我们的测试案例中,一个本地的JS触摸库在我们的WebView中处理得更好。 - J-Boss

8

对我来说,那些答案都没有帮助。

最终,我找到了原因和解决方案。原因是有很多CSS3过滤器(filter、-webkit-filter)。

解决方案

我在网页脚本中添加了WebView检测,以便将类“lowquality”添加到HTML body中。另外,您可以通过在WebView设置中设置用户代理来轻松跟踪WebView。然后,我创建了新的CSS规则。

body.lowquality * { filter: none !important; }

尽管设备速度更快,移动浏览器兼容性大大提高,以及其他原因,但5年后使用Webview的理由很少,这让人感到尴尬。不过还是感谢您对此进行了调查! - CQM
@CQM 我曾经遇到过同样的问题,后来找到了解决方案,所以想分享给大家 :) - l00k
我只是在开玩笑,这是我最古老的问题之一,再次感谢! - CQM
1
这在2016/2017年成为问题是荒谬的。任何移动GPU都不应该对CSS滤镜构成挑战。 - Adam Leggett

4
如果您的 Webview 中只有一些组件运行缓慢或卡顿,可以尝试将以下内容添加到元素的 CSS 中:
transform: translate3d(0,0,0);
-webkit-transform: translate3d(0,0,0);

这是唯一一种真正对我的Webview产生影响的速度优化技巧。但要小心不要过度使用!(您可以在此文章中了解更多关于这种技巧的信息。)

1
使用 will-change: transform - Adam Leggett

3

试试这个:

mWebView.setLayerType(View.LAYER_TYPE_HARDWARE, null);

3

如果您绑定了onclick事件,它可能在触摸屏上运行缓慢。

为了加快速度,我使用fastclick,它使用更快的触摸事件来模拟点击事件。


fastclick不再开发了...是的,触摸事件很慢,我只需要它能够工作,并且发现使用jquery可以通过$('#').on('touchstart', function() {...});解决速度问题,而不是使用onclick。 - CrandellWS

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接