欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

準(zhǔn)確測量 Android 應(yīng)用中 Activity 和 Fragment 的啟動時間的詳細(xì)過程

 更新時間:2024年07月06日 10:06:48   作者:長亭外的少年  
在 Android 應(yīng)用開發(fā)中,了解每個 Activity 和 Fragment 的啟動時間對于性能優(yōu)化至關(guān)重要,本文將介紹幾種方法來準(zhǔn)確測量 Activity 和 Fragment 的啟動時間,并提供實際操作步驟,以幫助提升應(yīng)用的響應(yīng)速度和用戶體驗,需要的朋友可以參考下

如何準(zhǔn)確測量 Android 應(yīng)用中 Activity 和 Fragment 的啟動時間

在 Android 應(yīng)用開發(fā)中,了解每個 Activity 和 Fragment 的啟動時間對于性能優(yōu)化至關(guān)重要。本文將介紹幾種方法來準(zhǔn)確測量 Activity 和 Fragment 的啟動時間,并提供實際操作步驟,以幫助提升應(yīng)用的響應(yīng)速度和用戶體驗。

1. 使用 adb shell am start -W 命令

adb shell am start -W 命令是一種簡單且直接的方法,用于測量 Activity 的啟動時間。該命令啟動指定的 Activity 并輸出相關(guān)的時間數(shù)據(jù)。以下是如何使用該命令,以及如何解決常見錯誤。

1.1 命令

adb shell am start -W -n <your.package.name>/<your.package.name.yourActivity>

1.2 輸出解釋

  • ThisTime: 當(dāng)前 Activity 的啟動時間。
  • TotalTime: 從應(yīng)用啟動到當(dāng)前 Activity 的總時間。
  • WaitTime: 系統(tǒng)等待時間。

1.3 啟動 Activity 并傳遞參數(shù)

使用 -e 選項傳遞參數(shù)

要傳遞鍵值對參數(shù),可以使用 -e 選項。-e 選項用于將一個字符串鍵值對傳遞給目標(biāo) Activity。如果有多個鍵值對需要傳遞,可以使用多個 -e 選項。

命令格式

adb shell am start -n <your.package.name>/<your.package.name.YourActivity> -e <key1> <value1> -e <key2> <value2> ...
  • -n <your.package.name>/<your.package.name.YourActivity>:指定要啟動的 Activity。
  • -e <key> <value>:指定要傳遞的參數(shù)及其對應(yīng)的值。key 是參數(shù)的名稱,value 是參數(shù)的值。

示例

應(yīng)用程序包名為 com.example.app,要啟動的 Activitycom.example.app.ui.MainActivity,并且需要傳遞兩個參數(shù):user_idsession_token。可以使用以下命令:

adb shell am start -n com.example.app/com.example.app.ui.MainActivity -e user_id 12345 -e session_token abcdef123456

傳遞多種數(shù)據(jù)類型

除了使用 -e 選項傳遞字符串參數(shù),還可以使用以下選項傳遞其他數(shù)據(jù)類型的參數(shù):

  • -e:傳遞字符串鍵值對。
  • -en:傳遞整數(shù)鍵值對。
  • -ef:傳遞浮點數(shù)鍵值對。
  • -el:傳遞長整型鍵值對。
  • -eb:傳遞布爾鍵值對。
  • -eia:傳遞整數(shù)數(shù)組鍵值對。
  • -efa:傳遞浮點數(shù)數(shù)組鍵值對。

示例

如果需要傳遞一個整數(shù)和一個布爾值參數(shù),可以使用以下命令:

adb shell am start -n com.example.app/com.example.app.ui.MainActivity -en max_retries 5 -eb is_active true

在這個例子中,max_retries 是一個整數(shù)參數(shù),is_active 是一個布爾參數(shù)。

解析傳遞的參數(shù)

在的 Activity 中,可以通過 Intent 對象來獲取傳遞的參數(shù)。例如:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent intent = getIntent();
        String userId = intent.getStringExtra("user_id");
        String sessionToken = intent.getStringExtra("session_token");
        // 使用獲取的參數(shù)
    }
}

對于其他數(shù)據(jù)類型的參數(shù),可以使用對應(yīng)的 Intent 方法進(jìn)行獲取,例如 getIntExtragetBooleanExtra 等。

通過使用 -e 及相關(guān)選項,可以方便地將參數(shù)傳遞給 Activity,在測試和調(diào)試過程中模擬各種條件。這使得驗證應(yīng)用程序的不同功能變得更加高效和靈活。

1.4 常見錯誤及解決方案

1.4.1 java.lang.SecurityException: Permission Denial

錯誤信息:

java.lang.SecurityException: Permission Denial: starting Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.example.myapp/.MainActivity mCallingUid=2000 } from null (pid=29129, uid=2000) not exported from uid 10600

原因: 當(dāng)嘗試啟動的 Activity 沒有配置為導(dǎo)出的或沒有適當(dāng)?shù)臋?quán)限時,會出現(xiàn)此錯誤。

解決方案:

修改 AndroidManifest.xml: 確保目標(biāo) Activity 已配置為 exported="true",這樣才能允許外部調(diào)用。

<activity
    android:name=".MainActivity"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

檢查權(quán)限: 確保應(yīng)用具有適當(dāng)?shù)臋?quán)限,或嘗試使用 adb 命令以 root 權(quán)限運行。

1.4.2 java.lang.SecurityException: Permission Denial: starting Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.example.myapp/.MainActivity } from null (pid=29219, uid=2000) not exported from uid 10600

錯誤信息:

java.lang.SecurityException: Permission Denial: starting Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.example.myapp/.MainActivity mCallingUid=2000 } from null (pid=29219, uid=2000) not exported from uid 10600

原因: 該錯誤通常表示目標(biāo) Activity 沒有正確配置為導(dǎo)出或啟動。即使 Activity 是導(dǎo)出的,它可能沒有正確設(shè)置 intent-filterlaunchMode。

解決方案:

配置 intent-filter: 確保 Activity 正確配置了 intent-filter,如果需要,它應(yīng)包括 MAINLAUNCHER 動作和類別。

<activity
    android:name=".MainActivity"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

檢查啟動模式: 如果 Activity 是內(nèi)部活動或不需要被外部啟動,考慮使用其他方法測試,或者設(shè)置 android:exported="true" 確保外部調(diào)用。

1.4.3 ActivityNotFoundException

錯誤信息:

android.content.ActivityNotFoundException: Unable to find explicit activity class {com.example.myapp/.MainActivity}; have you declared this activity in your AndroidManifest.xml?

原因: 該錯誤表示系統(tǒng)無法找到指定的 Activity。這可能是因為在 AndroidManifest.xml 中沒有正確聲明該 Activity,或包名和類名錯誤。

解決方案:

檢查 AndroidManifest.xml: 確保目標(biāo) Activity 已在 AndroidManifest.xml 中正確聲明。

<activity
    android:name=".MainActivity"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

核對包名和類名: 確保 adb 命令中的包名和類名與實際聲明的一致。

2. 手動記錄啟動時間

為了獲得更準(zhǔn)確的數(shù)據(jù),可以在代碼中手動記錄每個 Activity 的啟動時間。這種方法能夠提供更符合實際使用場景的數(shù)據(jù)。

2.1 代碼

在每個 Activity 的 onCreate 方法中記錄啟動時間:

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        long startTime = System.currentTimeMillis();
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        long elapsedTime = System.currentTimeMillis() - startTime;
        Log.d(TAG, "Activity startup time: " + elapsedTime + " ms");
    }
}

2.2 捕獲日志

使用 adb logcat 捕獲啟動時間日志:

adb logcat -s MainActivity

3. 使用 Application.ActivityLifecycleCallbacks 接口記錄activity啟動時長

為了自動記錄每個 Activity 的啟動時間,避免在每個 Activity 中重復(fù)編寫代碼,可以使用 Application.ActivityLifecycleCallbacks 接口。

3.1使用注解標(biāo)記中文名

首先,我們創(chuàng)建一個自定義注解來標(biāo)記 Activity 的中文名。

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface ChineseName {
    String value();
}

然后,在每個 Activity 類上使用這個注解。

import android.app.Activity;
import android.os.Bundle;
@ChineseName("我的Activity中文名")
public class MyActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Activity 其他代碼...
    }
}

3.2創(chuàng)建生命周期回調(diào)類

實現(xiàn) Application.ActivityLifecycleCallbacks

創(chuàng)建一個實現(xiàn) Application.ActivityLifecycleCallbacks 接口的類,以記錄每個 Activity 的啟動時間,并使用反射獲取中文名。

import android.app.Activity;
import android.app.Application;
import android.os.Bundle;
import android.util.Log;
public class ActivityLifecycleHandler implements Application.ActivityLifecycleCallbacks {
    private static final String TAG = "ActivityLifecycleHandler";
    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        long startTime = System.currentTimeMillis();
        activity.getWindow().getDecorView().post(() -> {
            long endTime = System.currentTimeMillis();
            long duration = endTime - startTime;
            String activityName = getChineseName(activity);
            Log.d(TAG, activityName + " creation time: " + duration + " ms");
        });
    }
    @Override
    public void onActivityStarted(Activity activity) {}
    @Override
    public void onActivityResumed(Activity activity) {}
    @Override
    public void onActivityPaused(Activity activity) {}
    @Override
    public void onActivityStopped(Activity activity) {}
    @Override
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}
    @Override
    public void onActivityDestroyed(Activity activity) {}
    private String getChineseName(Activity activity) {
        ChineseName annotation = activity.getClass().getAnnotation(ChineseName.class);
        if (annotation != null) {
            return annotation.value();
        } else {
            return activity.getClass().getSimpleName();
        }
    }
}

3.3 注冊生命周期回調(diào)

Application 類中注冊生命周期回調(diào):

public class MyApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(new AppLifecycleHandler());
    }
}

3.4 修改 AndroidManifest.xml

確保在 AndroidManifest.xml 中指定自定義的 Application 類:

<application
    android:name=".MyApp"
    ...>
    ...
</application>

3.5持續(xù)日志輸出

使用 adb logcat 命令捕獲啟動時間的日志輸出。

adb logcat -s AppLifecycleHandler

每次切換頁面或啟動新的 Activity 時,控制臺會輸出類似如下的日志信息:

07-04 14:23:45.123 1234-1234/com.example.myapp D/AppLifecycleHandler: MainActivity startup time: 150 ms
07-04 14:23:47.567 1234-1234/com.example.myapp D/AppLifecycleHandler: SettingsActivity startup time: 180 ms
07-04 14:23:47.567 1234-1234/com.example.myapp D/AppLifecycleHandler: 我的Activity中文名 startup time: 180 ms

這些日志顯示了每個 Activity 的啟動時間。通過這些數(shù)據(jù),可以分析和優(yōu)化應(yīng)用性能。

4.記錄所有 Fragment 啟動時間

同樣,可以通過覆蓋 Fragment 的生命周期方法來記錄 Fragment 的啟動時間。

4.1使用注解標(biāo)記中文名

同樣地,為 Fragment 使用相同的 ChineseName 注解。

import androidx.fragment.app.Fragment;
@ChineseName("我的Fragment中文名")
public class MyFragment extends Fragment {
    // Fragment 代碼...
}

4.2覆蓋 Fragment 生命周期方法

首先,創(chuàng)建一個基類 BaseFragment,覆蓋 FragmentonCreateView 方法,以記錄每個 Fragment 的啟動時間。

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
public class FragmentLifecycleHandler extends FragmentManager.FragmentLifecycleCallbacks {
    private static final String TAG = "FragmentLifecycleHandler";
    @Override
    public void onFragmentViewCreated(@NonNull FragmentManager fm, @NonNull Fragment f, @NonNull View v, @Nullable Bundle savedInstanceState) {
        long startTime = System.currentTimeMillis();
        f.getView().post(() -> {
            long endTime = System.currentTimeMillis();
            long duration = endTime - startTime;
            String fragmentName = getChineseName(f);
            Log.d(TAG, fragmentName + " view creation time: " + duration + " ms");
        });
    }
    private String getChineseName(Fragment fragment) {
        ChineseName annotation = fragment.getClass().getAnnotation(ChineseName.class);
        if (annotation != null) {
            return annotation.value();
        } else {
            return fragment.getClass().getSimpleName();
        }
    }
}

4.3完整代碼示例

所有的 Fragment 類繼承自 BaseFragment。

public class MyFragment extends BaseFragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_my, container, false);
    }
}

4.4持續(xù)日志輸出

使用 adb logcat 命令捕獲啟動時間的日志輸出。

adb logcat -s FragmentLifecycle

每次加載 Fragment 時,控制臺會輸出類似如下的日志信息:

07-04 14:23:45.123 1234-1234/com.example.myapp D/FragmentLifecycle: MyFragment startup time: 120 ms

這些日志顯示了每個 Fragment 的啟動時間。通過這些數(shù)據(jù),可以分析和優(yōu)化應(yīng)用性能。

5. 使用第三方工具

除了自定義實現(xiàn)外,還有許多第三方工具和庫可以幫助測量和優(yōu)化應(yīng)用的啟動時間。以下是一些常用的工具和庫:

5.1 阿里云移動監(jiān)控(Aliyun Mobile Monitoring)

阿里云移動監(jiān)控 提供了全面的性能監(jiān)控解決方案,包括啟動時間、崩潰分析、用戶行為分析等功能。

使用步驟:

1.集成 SDK: 在阿里云控制臺創(chuàng)建一個項目,并下載阿里云移動監(jiān)控 SDK。將 SDK 集成到的 Android 應(yīng)用中。具體步驟可以參考 阿里云官方文檔。

2.配置性能監(jiān)控: 在阿里云控制臺中配置性能監(jiān)控,包括啟動時間監(jiān)控和用戶行為分析。

3.查看性能數(shù)據(jù): 登錄阿里云控制臺,訪問 阿里云移動監(jiān)控 部分,可以查看應(yīng)用的啟動時間、崩潰報告以及用戶行為分析數(shù)據(jù)。

5.2 騰訊云移動分析(Tencent Cloud Mobile Analytics)

騰訊云移動分析 提供了全面的應(yīng)用性能監(jiān)控和用戶行為分析功能,適用于中國國內(nèi)的應(yīng)用開發(fā)者。

使用步驟:

1.集成 SDK

集成 SDK:

  • 在騰訊云控制臺創(chuàng)建一個項目,并下載騰訊云移動分析 SDK。
  • 將 SDK 集成到的 Android 應(yīng)用中。具體步驟可以參考 騰訊云官方文檔.

配置性能監(jiān)控:

  • 在騰訊云控制臺中配置性能監(jiān)控和用戶行為分析功能。

查看性能數(shù)據(jù):

  • 登錄騰訊云控制臺,訪問 騰訊云移動分析 部分,可以查看應(yīng)用的啟動時間、崩潰報告以及用戶行為數(shù)據(jù)。

5.3 百度移動統(tǒng)計(Baidu Mobile Statistics)

百度移動統(tǒng)計 提供了應(yīng)用性能監(jiān)控和用戶行為分析功能,幫助開發(fā)者了解應(yīng)用的性能和用戶行為。

使用步驟:

  • 集成 SDK
    • 在百度統(tǒng)計控制臺創(chuàng)建一個項目,并下載百度移動統(tǒng)計 SDK。
    • 將 SDK 集成到的 Android 應(yīng)用中。具體步驟可以參考 百度統(tǒng)計官方文檔.
  • 配置性能監(jiān)控
    • 在百度統(tǒng)計控制臺中配置性能監(jiān)控功能和用戶行為分析。
  • 查看性能數(shù)據(jù)
    • 登錄百度統(tǒng)計控制臺,訪問 百度移動統(tǒng)計 部分,可以查看應(yīng)用的啟動時間、崩潰報告和用戶行為數(shù)據(jù)。

5.4 Android Profiler

Android Profiler 是 Android Studio 提供的一套工具,可以幫助實時監(jiān)控應(yīng)用的性能,包括啟動時間、內(nèi)存使用、CPU 使用等。

使用步驟:

  • 啟動 Android Studio Profiler
    • 打開 Android Studio,運行的應(yīng)用。
    • 選擇 View > Tool Windows > Profiler,然后選擇的應(yīng)用進(jìn)程。
  • 監(jiān)控應(yīng)用啟動時間
    • 在 Profiler 窗口中,選擇 CPU 視圖。啟動應(yīng)用時,Profiler 會記錄
    • 啟動過程中 CPU 的使用情況,可以幫助了解啟動時間及其瓶頸。
  • 分析性能數(shù)據(jù)
    • Profiler 提供的時間線視圖和詳細(xì)的性能指標(biāo)可以幫助識別啟動過程中的性能問題。
    • 可以查看應(yīng)用的活動生命周期、內(nèi)存使用情況以及 CPU 占用情況,從而找到優(yōu)化的切入點。

5.5 LeakCanary

LeakCanary 是一個開源的內(nèi)存泄漏檢測庫,可以幫助檢測和修復(fù)內(nèi)存泄漏,從而間接優(yōu)化應(yīng)用的啟動時間和整體性能。

使用步驟:

集成 LeakCanary

build.gradle 文件中添加 LeakCanary 的依賴:

debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.10'

自動檢測內(nèi)存泄漏

LeakCanary 會自動監(jiān)控應(yīng)用的內(nèi)存泄漏并在發(fā)現(xiàn)泄漏時發(fā)出警告。

修復(fù)內(nèi)存泄漏

根據(jù) LeakCanary 提供的報告,識別并修復(fù)內(nèi)存泄漏問題,從而提高應(yīng)用的性能和啟動速度。 備注 Firebase Performance Monitoring

Firebase Performance Monitoring 是一個由 Google 提供的性能監(jiān)控工具,它可以幫助開發(fā)者監(jiān)控應(yīng)用的性能,包括啟動時間、網(wǎng)絡(luò)請求時間等。然而,由于某些 Google 服務(wù)在中國大陸可能會受到訪問限制,F(xiàn)irebase Performance Monitoring 的功能和數(shù)據(jù)傳輸可能會受到影響。

官方地址:

Firebase Performance Monitoring 官方文檔

總結(jié)

使用這些第三方工具,可以更全面地監(jiān)控和優(yōu)化應(yīng)用的啟動時間和整體性能。三方庫 和 Android Profiler 提供了實時的性能數(shù)據(jù)和分析功能,而 LeakCanary 可以幫助發(fā)現(xiàn)并修復(fù)內(nèi)存泄漏問題。這些工具和庫的結(jié)合使用,可以幫助提升應(yīng)用的用戶體驗和性能。

到此這篇關(guān)于準(zhǔn)確測量 Android 應(yīng)用中 Activity 和 Fragment 的啟動時間的詳細(xì)過程的文章就介紹到這了,更多相關(guān)Android Activity 和 Fragment 啟動時間內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論