Android webview ช้า


174

ของฉันandroid webviewsช้า นี่คือทุกอย่างตั้งแต่โทรศัพท์ไปจนถึง3.0+แท็บเล็ตที่มีสเปคเพียงพอมากกว่า

ฉันรู้ว่า webviews ควรจะ "จำกัด " แต่ฉันเห็นเว็บแอปทำด้วยช่องว่างโทรศัพท์ที่ต้องใช้ทุกประเภทCSS3และJQueryเวทมนตร์พวกเขาทำงานได้ดีและรวดเร็ว

ดังนั้นฉันจึงขาดอะไรไปมีอะไรบ้างmyWebview.SPEEDHACK(1)ที่ฉันสามารถใช้เร่งความเร็วของสิ่งต่างๆ

นอกจากนี้บางครั้งเนื้อหาของมุมมองเว็บของฉันไม่โหลดขึ้นมาแทนที่จะโหลดช้ามันก็ไม่โหลด สินทรัพย์ที่ฉันกำลังทดสอบถูกเก็บไว้ในเครื่องไม่มีข้อผิดพลาด


3
ฟังดูเหมือนคุณจะต้องโพสต์รหัส
Jasoneer

1
ซ้ำซ้อนกับประสิทธิภาพ
Ken White

1
@ KenWhite ยกเว้นคำถามนี้มีคำตอบเพิ่มเติมคำถามนี้มีคำตอบที่ดีกว่าและครอบคลุมมากขึ้นคำถามนี้มีสองเท่าหลายมุมมองทั้งสองคำถามมีอายุมากกว่าสองปีรุ่นของ Android ทั้งสองคำถามเหล่านี้จะล้าสมัย ... คุณออกจากการตั้งค่าสถานะนี้อย่างแน่นอนหรือไม่
CQM

@CQM: คำถามนี้ถูกตั้งค่าสถานะโดยอัตโนมัติโดยระบบเนื่องจากคำตอบที่ซ้ำกันของ George Mays ด้านล่าง หากคำตอบของเขาสามารถทำซ้ำทุกคำตอบเป็นคำตอบของการโพสต์หลายคนหนึ่งในนั้นคือซ้ำกันของอื่น ๆ คำถามที่เชื่อมโยงถูกโพสต์ (และตอบ) เป็นอันดับแรกตามวันที่โพสต์ ซ้ำกันเป็นซ้ำและโพสต์แรกเป็นต้นฉบับ (และคำตอบก่อนหน้านี้เช่นกัน) ฉันไม่ได้อะไรจากการตั้งค่าสถานะนี้ (และไม่ได้อยู่ในสถานที่แรก)
Ken White

1
นอกจากนี้อย่าใช้เหตุการณ์คลิกในแอปของคุณเพิ่มความล่าช้า 300ms เพื่อตอบสนองทุกการคลิกเพื่อพิจารณาว่าเป็นการคลิก ควรใช้ touchstart แทน ฉันสร้าง clickhandler ที่ใช้สองเหตุการณ์และใช้กิจกรรมที่ถูกเรียกครั้งแรก ฉันใช้ 'touchstart click' ดังนั้นจึงยังใช้งานได้โดยไม่มีหน้าจอสัมผัส
Codebeat

คำตอบ:


132

ขึ้นอยู่กับแอปพลิเคชันเว็บที่กำลังโหลด ลองวิธีการด้านล่าง:

ตั้งค่าลำดับความสำคัญการเรนเดอร์ที่สูงขึ้น (คัดค้านจาก 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);

46
ฉันเข้าใจว่าทำไมการตั้งค่าลำดับความสำคัญการเรนเดอร์ถึงสูงจะทำให้เร็วขึ้น แต่ทำไมปิดแคช?
Dimas Kotvan

39
เมธอด setRederPriority ถูกคัดค้านดูที่developer.android.com/reference/android/webkit/WebSettings.html
Victor Ionescu

6
ลิงก์ที่ถูกต้องสำหรับ setRenderPriority อยู่ที่นี่
Christopher Perry

2
ฉันจะวางรหัสนี้ในแอพของฉันได้ที่ไหน โปรดช่วย - ฉันมีปัญหาเดียวกันกับ WebView ที่มีความสำคัญต่อภารกิจ
Levchik

6
ทำไมคุณปิดแคช
Hassy31

52

การเพิ่มสิ่งนี้ลงandroid:hardwareAccelerated="true"ในรายการคือสิ่งเดียวที่ปรับปรุงประสิทธิภาพให้ฉันอย่างมาก

ข้อมูลเพิ่มเติมที่นี่: http://developer.android.com/guide/topics/manifest/application-element.html#hwaccel


1
นี่เป็นเพียงสำหรับ API v11 / Android 3.x และสูงกว่า
Ludwo

6
ระวังมีฮาร์ดแวร์ที่เกี่ยวข้องกับบั๊กแบบเปิดเร่ง WebViews ตามที่ระบุไว้ในคำถามstackoverflow.com/q/17059899/225341
Victor Ionescu

1
ฉันสังเกตว่าการปิดการเร่งด้วยฮาร์ดแวร์จริงทำให้แอปของฉันเร็วขึ้น ด้วยandroid:hardwareAccelerated="true"ภาพเคลื่อนไหว CSS 3D มีความล่าช้านานก่อนที่จะเริ่มการเลื่อน DIV ภายใน DIV แบบเลื่อนได้อื่นไม่ทำงานและแอปไม่เสถียรมากขึ้น
เออร์เนสส์คาร์ลสัน

1
ค่าเริ่มต้นคือ "true" หากคุณตั้งค่า minSdkVersion หรือ targetSdkVersion เป็น "14" หรือสูงกว่า
Vihaan Verma

37

ทางออกสำหรับเราตรงกันข้าม เราปิดใช้งานการเร่งด้วยฮาร์ดแวร์บน WebView เท่านั้น (แทนที่จะใช้กับแอพทั้งหมดในไฟล์ Manifest) โดยใช้รหัสนี้:

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


4
น่าเสียดายนี่เป็นการป้องกันคอมโพเนนต์วิดีโอ html5 ให้ทำงาน = /
Ja͢ck

ไม่ได้สังเกต เราใช้การดูวิดีโอเพื่อเล่นวิดีโอ: โชคดีที่เราเพิ่งต้องการวิดีโอแบบเต็มหน้าจอ เป็นวิธีแก้ปัญหาเป็นไปได้ที่จะมีการดูเว็บที่โปร่งใสและการดูวิดีโอที่เล่นในพื้นหลังแม้ว่าฉันรู้ว่ามันไม่เหมือนกัน
Ena

1
มีปัญหาอื่นกับการแก้ไขนี้ ในขณะที่สัมผัสหน้าจอเว็บกราฟิกจะได้รับการบิดเบือนเล็กน้อย ตัวอย่างเช่นหากคุณมีภาพที่มีวงกลมคุณจะสังเกตเห็นสี่เหลี่ยมเล็ก ๆ (พิกเซล) บนมันแทนที่จะเป็นเส้นเรียบ ฉันบอกได้เลยว่าการแก้ไข Android 4.3 นั้นไม่มีประโยชน์เลยมันไม่มีปัญหาเรื่องประสิทธิภาพ
Ena

ขออภัยเล็กน้อยสำหรับ Android สามารถวางได้โดยตรงในรายการหุ่นยนต์เนื่องจากไฟล์รายการนั้นเป็น XML หรือนี่ควรจะถูกตรวจสอบในซอร์สโค้ดเมื่อโหลด webview ขออภัยสำหรับคำถาม noob
xMythicx

1
หลังจากเพิ่มแล้วให้รับข้อผิดพลาดนี้WebView not displayed because it is too large to fit into a software layer (or drawing cache), needs 11534400 bytes, only 8294400 available
นักพัฒนา

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 ฉันเดาว่ามันจะทำงานได้ดีขึ้นด้วยการเร่งฮาร์ดแวร์


1
สิ่งนี้ใช้ได้กับฉันใน WebViews ที่มีภาพเคลื่อนไหวและการเลื่อนที่ไม่ดี
cal

เป็นฉันหรือว่า 'คนอื่น' ของคุณทำเช่นเดียวกับคุณถ้า?
Codebeat

Erwinus one ใช้สำหรับ type_SOFTWARE และฮาร์ดแวร์อื่น ๆ
user2582318

9

ฉันมีปัญหาเดียวกันนี้และต้องทำงานให้เสร็จ ฉันลองใช้วิธีแก้ไขปัญหาเหล่านี้ แต่ท้ายที่สุดแล้วประสิทธิภาพการทำงานอย่างน้อยสำหรับการเลื่อนก็ไม่ได้ปรับปรุงเลย ดังนั้นนี่คือการแก้ปัญหาที่ฉันได้แสดงและคำอธิบายว่าทำไมมันถึงได้ผลสำหรับฉัน

หากคุณมีโอกาสสำรวจเหตุการณ์ลากเพียงเล็กน้อยโดยสร้างคลาส "MiWebView" เขียนทับวิธี "onTouchEvent" และอย่างน้อยพิมพ์เวลาที่เหตุการณ์ลากเกิดขึ้นทุกครั้งคุณจะเห็นว่าพวกมันถูกแยกออก ในเวลาสำหรับ (ลงไป) 9ms ออกไป นั่นเป็นเวลาสั้น ๆ ในระหว่างเหตุการณ์

ดูที่รหัสแหล่งที่มาของ WebViewและดูฟังก์ชั่น onTouchEvent มันเป็นไปไม่ได้เลยที่โปรเซสเซอร์จะจัดการในเวลาน้อยกว่า 9ms (ฝันต่อไป !!! นั่นเป็นเหตุผลที่คุณเห็น "พลาดการลากในขณะที่เรากำลังรอการตอบสนองของ WebCore สำหรับการสัมผัสลง" ข่าวสาร รหัสไม่สามารถจัดการได้ทันเวลา

จะแก้ไขได้อย่างไร? ก่อนอื่นคุณไม่สามารถเขียนรหัส onTouchEvent ซ้ำเพื่อปรับปรุงได้มันมากเกินไป แต่คุณสามารถ "เยาะเย้ยมัน" เพื่อ จำกัด อัตราเหตุการณ์สำหรับการลากการเคลื่อนไหวสมมติว่า 40ms หรือ 50ms (ขึ้นอยู่กับโปรเซสเซอร์)

กิจกรรมการสัมผัสทั้งหมดเป็นดังนี้: ACTION_DOWN -> ACTION_MOVE ...... ACTION_MOVE -> ACTION_UP ดังนั้นเราจำเป็นต้องให้การเคลื่อนไหวขึ้นและลงและกรองอัตราการย้าย (เหล่านี้คือคนเลว)

และนี่คือวิธีที่จะทำ (คุณสามารถเพิ่มประเภทเหตุการณ์เช่นการสัมผัส 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 อย่างไรก็ตามมันเป็นทางออกที่ดีที่สุดที่ฉันพบอย่างน้อยก็สำหรับความต้องการเฉพาะของฉัน


ฉันต้องการจะชี้ให้เห็นว่าซอร์สโค้ดของเว็บวิวที่คุณโพสต์นั้นมาจากปี 2010
CQM

มันใช้งานไม่ได้มันเลื่อนไม่ราบรื่นฉันไม่รู้สึกถึงความแตกต่าง
neevek

ฉันใช้การตั้งค่านี้ถึงขีด จำกัด สูงสุด 80 แต่จริงๆแล้วมันดูเหมือนจะไม่ปรับปรุงประสิทธิภาพ แต่มันจับเหตุการณ์การย้ายบางอย่าง คุณทำอะไรได้บ้าง
Ragnar

ได้อ่านแล้วว่าเหตุการณ์การคลิกนั้นช้ากว่าการสัมผัสเหตุการณ์ถึง 6 เท่า เพื่อหลีกเลี่ยงความล่าช้าคุณสามารถใช้ $ ('# button'). on ('touchstart click', function () {action here; return false;});
Codebeat

นอกจากนี้อย่าใช้เหตุการณ์การคลิกในแอพ html ของคุณเพิ่มความล่าช้า 300ms เพื่อตอบสนองทุกการคลิกเพื่อพิจารณาว่าเป็นการคลิก ควรใช้ touchstart แทน ฉันสร้าง clickhandler ที่ใช้สองเหตุการณ์และใช้กิจกรรมที่ถูกเรียกครั้งแรก ฉันใช้ 'touchstart click' ดังนั้นจึงยังใช้งานได้โดยไม่มีหน้าจอสัมผัส
Codebeat

9

ฉันลองข้อเสนอทั้งหมดเพื่อแก้ไขปัญหาประสิทธิภาพการแสดงผลในแอพ phonegap ของฉัน แต่ไม่มีอะไรจริง ๆ ใช้งานได้

ในที่สุดหลังจากค้นหาได้ทั้งวันฉันก็ทำ ฉันตั้งค่าไว้ภายในแท็ก (ไม่ใช่แท็ก) ของ AndroidManifest

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

ตอนนี้แอพทำงานในลักษณะเดียวกับเว็บเบราว์เซอร์ของฉัน ดูเหมือนว่าหากการเร่งความเร็วฮาร์ดแวร์ไม่ใช่คุณสมบัติที่ดีที่สุดเสมอไป ...

ปัญหาโดยละเอียดที่ฉันมี: https://stackoverflow.com/a/24467920/3595386


2
การปิดใช้งานการเร่งด้วยฮาร์ดแวร์ทำได้น่ากลัวสำหรับฉัน webview ช้ามากในการเลื่อน
AbdelHady

5

ไม่มีคำตอบเหล่านั้นไม่เป็นประโยชน์สำหรับฉัน

ในที่สุดฉันก็พบเหตุผลและทางออก เหตุผลก็คือตัวกรอง CSS3 จำนวนมาก (ตัวกรอง, -webkit-filter)

สารละลาย

ฉันได้เพิ่มการตรวจจับของ WebView ในสคริปต์ของหน้าเว็บเพื่อเพิ่มคลาส "lowquality" ให้กับเนื้อหา HTML BTW คุณสามารถติดตาม WebView ได้อย่างง่ายดายโดยการตั้งค่า user-agent ในการตั้งค่า WebView จากนั้นฉันก็สร้างกฎ CSS ใหม่

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

อึดอัดใจเมื่อ 5 ปีต่อมามีเหตุผลน้อยมากที่จะใช้เว็บวิวแม้ว่าอุปกรณ์จะเร็วขึ้น แต่ประสิทธิภาพการทำงานร่วมกับเบราว์เซอร์บนมือถือก็เพิ่มขึ้นอย่างมากและเหตุผลอื่น ๆ ขอบคุณสำหรับการดูมันแม้ว่า!
CQM

@CQM ฉันมีปัญหาเดียวกันผมพบว่าวิธีการแก้ปัญหาดังนั้นผมจึงอยากจะแบ่งปันมัน :)
l00k

ฉันแค่กำลังเผชิญกับปัญหานี้เป็นหนึ่งในคำถามที่เก่าแก่ที่สุดของฉันขอบคุณอีกครั้ง!
CQM

1
มันไร้สาระว่านี่เป็นปัญหาในปี 2016/2017 ไม่ควรใช้ตัวกรอง CSS ใด ๆ กับ GPU มือถือ
Adam Leggett

4

หากมีเพียงไม่กี่องค์ประกอบของมุมมองเว็บของคุณที่ช้าหรือช้าลองเพิ่มสิ่งนี้ไปยังองค์ประกอบ CSS:

transform: translate3d(0,0,0);
-webkit-transform: translate3d(0,0,0);

นี่เป็น speedhack เดียวที่มีผลกระทบต่อ webview ของฉันจริงๆ แต่ระวังอย่าให้มากเกินไป! (คุณสามารถอ่านเพิ่มเติมเกี่ยวกับการแฮ็คในบทความนี้ )


1
will-change: transformใช้
Adam Leggett


3

หากคุณมีผลผูกพันกับonclickเหตุการณ์อาจทำให้หน้าจอสัมผัสช้า

เพื่อให้เร็วขึ้นฉันใช้fastclickซึ่งใช้กิจกรรมการสัมผัสที่เร็วกว่ามากเพื่อเลียนแบบเหตุการณ์การคลิก


fastclick ไม่ได้รับการพัฒนาอีกต่อไป ... ใช่กิจกรรมการสัมผัสช้าและฉันต้องการให้มันทำงานและเจอกับ jQuery ปัญหาความเร็วสามารถแก้ไขได้โดยใช้$('#').on('touchstart', function() {...});นอกคอก onclick
CrandellWS
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.