আপনার অ্যাপ প্রথমবার WebView ব্যবহার করলে, সিস্টেম নির্দিষ্ট স্টার্টআপ টাস্ক পারফর্ম করে।
এই স্টার্টআপ প্রসেসটি ভারী। ডিফল্ট হিসেবে, অ্যাপটি প্রথমবার android.webkit বা androidx.webkit প্যাকেজের মধ্যে অনেক API কল করলে বা WebView ট্যাগ আছে এমন লেআউট ইনফ্লেট করলে, এটি UI থ্রেডে
ইমপ্লিসিটভাবে ঘটে।
এটি কেন গুরুত্বপূর্ণ
যেহেতু এই ইমপ্লিসিট স্টার্টআপ সম্পূর্ণভাবে মূল থ্রেডে ঘটে, তাই এটি আপনার অ্যাপকে ব্যবহারকারীর ইনপুট প্রসেস করা থেকে ব্লক করে এবং অ্যাপ্লিকেশন সাড়া দিচ্ছে না (ANR) সংক্রান্ত সমস্যার ঝুঁকি উল্লেখযোগ্যভাবে বাড়িয়ে দেয়। Android কীভাবে সিঙ্গল-থ্রেডেড এক্সিকিউশন মডেল ম্যানেজ করে সেই সম্পর্কে আরও জানতে, প্রসেস ও থ্রেড ওভারভিউ দেখুন।
ইমপ্লিসিট স্টার্টআপের জন্য ট্রিগার
নিম্নলিখিত উপায়ে ইমপ্লিসিট স্টার্টআপ ট্রিগার করা যেতে পারে:
- প্রোগ্রাম্যাটিক্যালি:
WebSettings.getUserAgentString()-এর মতো API কল করা। - লেআউট ব্যবহার করা:
<WebView>অন্তর্ভুক্ত আছে এমন XML রিসোর্সেsetContentView()বাlayoutInflater.inflate()কল করা।
ইমপ্লিসিট স্টার্টআপ আপনার ব্যবসার মেট্রিককেও নেতিবাচকভাবে প্রভাবিত করতে পারে, যেমন অ্যাপ
স্টার্টআপ টাইম এবং টাইম-টু-ফার্স্ট-ডিসপ্লে। আপনার অ্যাপের জন্য ইমপ্লিসিট ইনিশিয়ালাইজেশন
উপযুক্ত না হলে, পরিবর্তে startUpWebView ব্যবহার করুন।
এই পৃষ্ঠায় আলোচনা করা হয়েছে যে কীভাবে
startUpWebView API ব্যবহার করে WebView স্টার্টআপ পারফর্ম্যান্স অপ্টিমাইজ করা যায়।
WebView স্টার্টআপের নিয়ন্ত্রণ নিন
পারফর্ম্যান্স উন্নত করতে এবং ANR কমাতে, Jetpack Webkit লাইব্রেরিতে উপলভ্য
startUpWebView API ব্যবহার করুন। এই API আপনাকে WebView কখন চালু হবে তার উপর স্পষ্ট নিয়ন্ত্রণ দেয়। এটি স্টার্ট-আপ ওয়ার্কলোডের একটি উল্লেখযোগ্য পরিমাণ ব্যাকগ্রাউন্ড থ্রেডে শিফট করে এবং UI থ্রেডে অবশ্যই হতে হবে এমন যেকোনও কাজকে একটি বড় মনোলিথিক ব্লকের পরিবর্তে চাঙ্কে করার সুবিধা দেয়। এটি আপনার UI থ্রেডকে মুক্ত করে যাতে এটি সমান্তরালভাবে অন্যান্য গুরুত্বপূর্ণ অ্যাপ টাস্কগুলি পরিচালনা করতে পারে, যা ব্যবহারকারীর অভিজ্ঞতাকে ব্লক করার সম্ভাবনা কমিয়ে দেয়।
API androidx.webkit.WebViewOutcomeReceiver কলব্যাক ব্যবহার করে, যা আপনাকে
সফল ইনিশিয়ালাইজেশন ট্র্যাক করতে দেয়।
এই API ব্যবহার করতে, আপনার build.gradle ফাইলে Jetpack Webkit লাইব্রেরি যোগ করুন।
আপনি ভার্সন 1.16.0 বা তার পরবর্তী ভার্সন ব্যবহার করছেন কিনা তা নিশ্চিত করুন:
dependencies {
implementation("androidx.webkit:webkit:1.16.0")
}
startUpWebView API ব্যবহার করুন
আপনার অ্যাপকে কখন WebView দেখাতে হবে তার উপর নির্ভর করে আপনি কীভাবে স্টার্ট-আপ ফ্লো অপ্টিমাইজ করবেন।
WebView ক্রিটিকাল পাথে না থাকলে
আপনার অ্যাপে যদি অবিলম্বে WebView লোড করার প্রয়োজন না হয়, তাহলে আপনি
ইনিশিয়ালাইজেশন খরচ সম্পূর্ণভাবে লুকাতে পারেন। আপনার অ্যাপের লাইফসাইকেলের শুরুতে startUpWebView কল করুন
এবং সাকসেস কলব্যাক ফায়ার হওয়ার জন্য অপেক্ষা করুন।
সাধারণত, অন্যান্য WebView API কল করার আগে আপনার কলব্যাকের জন্য অপেক্ষা করা উচিত। আপনি
startUpWebView ট্রিগার করলে, কিন্তু অন্যান্য WebView কম্পোনেন্ট স্পর্শ করার আগে এটি শেষ হওয়ার জন্য অপেক্ষা না করলে,
ইনিশিয়ালাইজেশন সম্পূর্ণ হওয়ার জন্য অপেক্ষা করার সময় সিস্টেম UI থ্রেড ব্লক করে দেয়। আপনার অ্যাপ ব্যাকগ্রাউন্ডে আগে থেকে সম্পূর্ণ হওয়া কাজ থেকে
কিছু পারফর্ম্যান্স সংক্রান্ত সুবিধা পেতে পারে, তবে সর্বাধিক সুবিধা নয়।
WebView ক্রিটিকাল পাথে থাকলে
আপনার অ্যাপের মূল ব্যবহারকারীর অভিজ্ঞতার জন্য অবিলম্বে WebView-এর প্রয়োজন হলে, WebView চালু হওয়ার জন্য
অপেক্ষা করা আপনার পক্ষে সম্ভব নাও হতে পারে। এই পরিস্থিতিতে, অ্যাপ লাইফসাইকেলে (যেমন Application.onCreate-এ)
যত তাড়াতাড়ি সম্ভব আপনাকে startUpWebView কল করতে হবে,
তবে কলব্যাক ট্রিগার হওয়ার জন্য অপেক্ষা করবেন না। পরিবর্তে, WebView API-এর প্রয়োজন হলে সরাসরি সেটি ব্যবহার করুন।
অ্যাসিঙ্ক্রোনাস স্টার্টআপ থেকে সর্বাধিক সুবিধা পেতে, WebView ইনস্ট্যান্টিয়েট করা বা WebView API কল করা যতক্ষণ না পর্যন্ত অন্য কোনও ক্রিটিক্যাল-পাথ UI থ্রেড অপারেশন চালানোর জন্য বাকি থাকে (যেমন ইনফ্লেটিং লেআউট হায়ারার্কি, অন্যান্য SDK ইনিশিয়ালাইজ করা বা প্রাথমিক ফ্রেম ড্র করা) ততক্ষণ পর্যন্ত স্থগিত রাখুন।
আপনি যদি startUpWebView কল করেন এবং তারপরেই মূল থ্রেডে WebView API ইনভোক করেন, তাহলে ইনিশিয়ালাইজেশন সম্পূর্ণ হওয়ার জন্য UI থ্রেড ব্লক হয়ে যায়। এই পরিস্থিতিতে, পারফর্ম্যান্সের কোনও সুবিধা নেই।
WebView ব্যবহার যদি ক্রিটিক্যাল পাথে হয়, কিন্তু আপনি WebView সম্পূর্ণভাবে স্টার্টআপ করতে না চান, তাহলে আপনি বেছে নিয়ে WebView স্টার্টআপ টাস্ক চালাতে পারেন, যা ব্যাকগ্রাউন্ড থ্রেডে চলতে পারে এবং অন্যান্য অ্যাপ ক্রিটিক্যাল টাস্কের জন্য UI থ্রেড খালি করে দেয়। এর জন্য আপনি
shouldRunUiThreadStartUpTasks(false) ব্যবহার করতে পারেন।
আপনার অ্যাপের লাইফসাইকেলের পরবর্তী পর্যায়ে, UI থ্রেডে বাকি থাকা স্টার্টআপ টাস্ক সম্পূর্ণ করতে আপনি
shouldRunUiThreadStartUpTasks(true)-এর সাথে আবার startUpWebView-কে কল করতে
পারবেন। আপনি সেই মুহূর্তে কলব্যাকের জন্য অপেক্ষা করবেন কিনা তা নির্ভর করে
WebView-এর ব্যবহার ক্রিটিক্যাল পাথে আছে কিনা তার উপর।
প্রয়োগের উদাহরণ
API androidx.webkit.WebViewOutcomeReceiver কলব্যাক ব্যবহার করে, যা আপনাকে
সফল ইনিশিয়ালাইজেশন ট্র্যাক করতে বা ডায়াগনস্টিক সংক্রান্ত সমস্যা সমাধান করতে দেয়।
আপনার অ্যাপের বিভিন্ন অংশ থেকে একাধিকবার startUpWebView কল করা নিরাপদ।
আমরা সাজেস্ট করি যে আপনি একটি সাধারণ রিট্রাই লুপ প্রয়োগ করা এড়িয়ে চলুন।
অ্যাসিঙ্ক্রোনাস ইনিশিয়ালাইজেশনের জন্য কীভাবে
WebViewCompat.startUpWebView API ব্যবহার করতে হয় তা নিম্নলিখিত কোড স্যাম্পেল থেকে জানতে পারবেন।
Kotlin
import android.content.Context
import android.util.Log
import androidx.webkit.WebViewCompat
import androidx.webkit.WebViewOutcomeReceiver
import androidx.webkit.WebViewStartUpConfig
import androidx.webkit.WebViewStartUpResult
import androidx.webkit.WebViewStartupException
import java.util.concurrent.Executors
fun initializeWebView(context: Context) {
// 1. Create a startup configuration specifying the background thread
// that WebView will use to run its initialization tasks.
val startUpConfig = WebViewStartUpConfig.Builder(
Executors.newSingleThreadExecutor()
).build()
// 2. Trigger WebView startup asynchronously
WebViewCompat.startUpWebView(
context,
startUpConfig,
object : WebViewOutcomeReceiver<WebViewStartUpResult, WebViewStartupException> {
override fun onResult(result: WebViewStartUpResult) {
// Success: The WebView has finished its background initialization.
// This callback is guaranteed to be invoked on the UI thread.
setupWebView()
}
override fun onError(error: WebViewStartupException) {
// Failure: The initialization encountered a startup exception.
Log.e("WebViewStartup", "Failed to initialize WebView", error)
}
}
)
}
জাভা
import android.content.Context;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.webkit.WebViewCompat;
import androidx.webkit.WebViewOutcomeReceiver;
import androidx.webkit.WebViewStartUpConfig;
import androidx.webkit.WebViewStartUpResult;
import androidx.webkit.WebViewStartupException;
import java.util.concurrent.Executors;
public void initializeWebView(Context context) {
// 1. Create the startup configuration specifying the background thread pool
// to handle internal non-UI initialization processes.
WebViewStartUpConfig startUpConfig = new WebViewStartUpConfig.Builder(
Executors.newSingleThreadExecutor()
).build();
// 2. Trigger WebView startup asynchronously
WebViewCompat.startUpWebView(
context,
startUpConfig,
new WebViewOutcomeReceiver<WebViewStartUpResult, WebViewStartupException>() {
@Override
public void onResult(@NonNull WebViewStartUpResult result) {
// Success: The WebView has finished its background initialization.
// This callback is invoked directly on the UI thread.
setupWebView();
}
@Override
public void onError(@NonNull WebViewStartupException error) {
// Failure: Handled using the concrete WebViewStartupException
Log.e("WebViewStartup", "Failed to initialize WebView", error);
}
}
);
}
অ্যাসিঙ্ক্রোনাস স্টার্টআপ সংক্রান্ত সমস্যার সমাধান করা
startUpWebView থেকে প্রত্যাশিত পারফর্ম্যান্সের সুবিধা না পেলে, এটি প্রায়শই
কারণ আপনার কল কার্যকর হওয়ার আগে আপনার অ্যাপের অন্য কোথাও WebView অন্তর্নিহিতভাবে শুরু করা হচ্ছে। এটি নিম্নলিখিত কারণে হতে পারে:
অ্যাপ লাইফসাইকেলের শুরুতে থার্ড-পার্টি লাইব্রেরি বা SDK ইনিশিয়ালাইজ করা হয়েছে।
ContentProvidersআপনার APK-তে ইনজেক্ট করা হয়েছে যা অ্যাপ স্টার্টআপের সময় WebView API ট্রিগার করে।লেআউট ইনফ্লেশন বা প্রোগ্রাম্যাটিক কল (যেমন, ইউজার এজেন্ট স্ট্রিং ফেচ করা) যা অপ্রত্যাশিতভাবে আগে ঘটে।
এই অপ্রত্যাশিত ইনিশিয়ালাইজেশন কোথায় এবং কেন হচ্ছে তা ডায়াগনসিস করতে আপনাকে সাহায্য করার জন্য, WebViewStartUpResult অবজেক্ট বিল্ট-ইন অডিটিং
ক্ষমতা প্রদান করে:
getUiThreadBlockingStartUpLocations():StartUpLocationঅবজেক্টের তালিকা দেখায় যা সেইসব লোকেশনকে দেখায় যেখানে WebView স্টার্টআপ টাস্ক মূল UI থ্রেডকে ব্লক করেছে।getNonUiThreadBlockingStartUpLocations(): নির্দিষ্ট কল সাইট রিটার্ন করে যেখানে স্টার্টআপ টাস্ক চালানোর ফলে ব্যাকগ্রাউন্ড থ্রেড ব্লক হয়ে গেছে।
প্রতিটি StartUpLocation-এ একটি স্ট্যাক ট্রেস থাকে যা আপনি লগ বা পরীক্ষা করে দেখতে পারেন
কোন ক্লাস এবং পদ্ধতি ইনিশিয়ালাইজেশন ট্রিগার করেছে তা খুঁজে বের করতে।
প্রয়োগের উদাহরণ
আপনার স্টার্টআপ পাথ অডিট করতে onResult কলব্যাকের মধ্যে এইসব লোকেশন
আপনি পরীক্ষা করতে পারবেন:
override fun onResult(result: WebViewStartUpResult) {
// Check if WebView startup was blocked on the UI thread prior to or during initialization
val uiBlockingLocations = result.getUiThreadBlockingStartUpLocations()
if (!uiBlockingLocations.isNullOrEmpty()) {
for (location in uiBlockingLocations) {
// Log the stack trace of the call site that triggered the UI-blocking startup
Log.w("WebViewDebug", "WebView startup blocked the UI thread here:", location.getStack())
}
} else {
Log.i("WebViewDebug", "Excellent! No UI-blocking WebView startup detected.")
}
// Check where background initialization tasks were executed
val backgroundLocations = result.getNonUiThreadBlockingStartUpLocations()
backgroundLocations?.forEach { location ->
Log.d("WebViewDebug", "WebView background startup occurred at: ${location.getStack()}")
}
setupWebView()
}
অডিট চলাকালীন কীভাবে এই ডেটা ব্যবহার করবেন
আপনার অ্যাপের WebView স্টার্টআপ অডিট করার সময়, ডায়াগনস্টিক ডেটা বিশ্লেষণ করতে এবং পারফর্ম্যান্সের বাধা দূর করতে নিম্নলিখিত কৌশলগুলি ব্যবহার করুন:
অপ্রত্যাশিত স্ট্যাক ট্রেস খুঁজুন:
getUiThreadBlockingStartUpLocations()খালি না থাকলে, প্রিন্ট করা স্ট্যাক ট্রেস দেখুন। আপনি যদি থার্ড-পার্টি SDK বা অপ্রত্যাশিত কম্পোনেন্টের ক্লাস দেখতে পান, তাহলে আপনি একটি ইমপ্লিসিট ইনিশিয়ালাইজেশন বটলেনেক খুঁজে পেয়েছেন।কল অর্ডার যাচাই করুন: আপনার লগ আউটপুট যদি দেখায় যে আপনার ম্যানুয়াল
startUpWebViewকলের আগে একটি অন্তর্নিহিত ইনিশিয়ালাইজেশন হয়েছে, তাহলে আপনার অ্যাপেstartUpWebViewইনিশিয়ালাইজেশন আগে নিয়ে যেতে হবে অথবা WebView-নির্ভর টাস্ক দেরিতে করার জন্য সমস্যা সৃষ্টিকারী SDK কনফিগার করতে হবে।
আগের ওয়ার্কঅ্যারাউন্ড থেকে মাইগ্রেট করা
অতীতে, আপনি হয়ত ব্যাকগ্রাউন্ড থ্রেডে WebView ইনিশিয়ালাইজেশন জোর করে করার জন্য ইউজার এজেন্ট স্ট্রিং ফেচ করার মতো এক্সপ্লিসিট ওয়ার্কঅ্যারাউন্ড ব্যবহার করেছেন।
এইসব সমাধানকে কাজ চালানোর মতো পদ্ধতি হিসেবে বিবেচনা করা হয় এবং এগুলির অন্তর্নিহিত
আচরণ আসন্ন রিলিজে পরিবর্তিত হতে পারে। WebView স্টার্ট-আপ ট্রিগার বা ম্যানেজ করার জন্য আপনার অ্যাপ যদি কোনও নির্দিষ্ট,
ডকুমেন্ট করা হয়নি এমন ওয়ার্কঅ্যারাউন্ডের উপর নির্ভর করে, তাহলে আমরা
startUpWebView API ব্যবহার করার সাজেশন দিই। startUpWebView API, Android ও WebView-এর সেইসব ভার্সনে কাজ করে যেগুলি Jetpack Webkit লাইব্রেরিতে কাজ করে।
অ্যাপের স্থিতিস্থাপকতা ও স্থিতিশীলতা নিশ্চিত করা
Jetpack Webkit ইমপ্লিমেন্টেশন ব্যবহার করলে, সম্পূর্ণ Android ইকোসিস্টেম জুড়ে একই ধরনের আচরণ নিশ্চিত করতে সাহায্য করে। এই API-এর একটি মূল সুবিধা হল এর স্থিতিস্থাপকতা: পুরনো ডিভাইসে যেখানে নতুন অপ্টিমাইজেশন উপলভ্য নয়, সেখানে API ম্যানুয়াল ওয়ার্কঅ্যারাউন্ডের সাথে পারফর্ম্যান্সের সমতা বজায় রাখে। এর ফলে আপনি পুরনো ডিভাইসের পারফর্ম্যান্সের উপর কোনও প্রভাব না ফেলেই নতুন ডিভাইসে আধুনিক স্টার্টআপের সুবিধা গ্রহণ করতে পারবেন।
WebView স্টার্ট-আপ অপ্টিমাইজ করার ফলে অ্যাপ লঞ্চের সময় ANR সমস্যার ঝুঁকি কমে গেলেও, রানটাইম রেন্ডারার ক্র্যাশ এবং সিস্টেম মেমরি রিক্লেমেশনের হাত থেকে
আপনার অ্যাপকে সুরক্ষিত রাখতে হবে। আপনার WebView চালু হওয়ার পরে অ্যাপের সামগ্রিক স্থিতিশীলতা বজায় রাখতে, WebView বন্ধ হয়ে যাওয়া ম্যানেজ করা দেখুন। এছাড়াও, WebView.saveState()
ব্যবহার করে ব্যাকগ্রাউন্ড প্রসেস বন্ধ করার সময় ব্যবহারকারীর স্টেট সংক্রান্ত তথ্য সেভ করে রাখুন এবং WebView স্টেট দক্ষতার সাথে ম্যানেজ করুন লিঙ্কে দেওয়া মেমরি-সেফ প্র্যাক্টিস অনুসরণ করুন।
startUpWebView API সম্পর্কে কোনও সমস্যা হলে বা মতামত থাকলে, পাবলিক ইস্যু ট্র্যাকারে বাগ ফাইল করুন।