在您为亚马逊Fire设备构建应用时,让您的功能始终正常运作无疑非常重要。构建优秀的应用也意味着要创造一种流畅可靠的用户体验。崩溃、延迟和糟糕的用户界面交互会导致负面评价,甚至导致用户卸载应用。没有开发者希望看到这种事情发生。
因此,解决性能问题并保持应用稳定是应用开发者使命当中非常重要的部分。这两个方面是让用户满意并确保应用成功的关键。值得庆幸的是,借助亚马逊开发者控制台中的工具(例如应用运行状况洞察控制面板),可以更轻松地发现问题并进行正确的修复。
本指南将引导您了解如何理解控制面板以及需要注意的方面。您会收获许多提高应用性能和稳定性的技巧。您准备好确保应用在每个Fire设备上都有上佳表现了吗?那么我们开始吧!
应用运行状况洞察控制面板是一种强大的工具,可帮助您了解应用的表现。它提供关键指标和有用见解,让您可以专注于解决最重要的问题。
要访问它,您需要有上线应用。要开始使用,请执行以下操作:
控制面板分为两个主要部分:性能控制面板和稳定性控制面板。每个部分都侧重于应用运行状况的一个特定方面。
有了此类数据,您不必再为寻找问题根源而烦恼,可以清楚地看到问题所在并立即解决问题。
对于开发者而言,时间很宝贵。控制面板让您无需在数量庞大的日志中挖掘有用信息或被动等待用户投诉。它能够突显应用中最关键的问题,让您优先考虑对用户体验影响最大的修复措施。通过尽早解决这些问题,您可以减少负面评价并提高留存率。
性能控制面板可帮助您衡量应用的效率。通过关注数项关键指标,您可以发现和解决影响用户体验的瓶颈。
应用延迟指标跟踪应用启动方式的两个关键方面:应用启动时间和准备就绪时间。
这两个指标都至关重要,因为它们会影响用户对速度和响应能力的感知。超出这些基准可能会让人感觉应用速度缓慢,并导致用户懊恼。
要缩短应用的启动时间和准备就绪时间,您可以采取以下措施:
public void serialize(Context context, String filename,
Serializable object) throws Exception {
FileOutputStream fOut =
context.openFileOutput(filename, Context.MODE_PRIVATE);
ObjectOutputStream oOut = new ObjectOutputStream(fOut);
oOut.writeObject(object);
oOut.close();
}
public Object deserialize(Context context,
String filename) throws Exception {
FileInputStream fIn = context.openFileInput(filename);
ObjectInputStream oIn = new ObjectInputStream(fIn);
Object result = oIn.readObject();
oIn.close();
return result;
}
private val executor = Executors.newSingleThreadExecutor()
fun <T : Serializable> serialize(context: Context, filename: String, data: T) {
executor.execute {
try {
context.openFileOutput(filename, Context.MODE_PRIVATE).use { fileOut ->
ObjectOutputStream(fileOut).use { objOut ->
objOut.writeObject(data)
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
fun <T : Serializable> deserialize(context: Context, filename: String, callback: (T?) -> Unit) {
executor.execute {
val result: T? = try {
context.openFileInput(filename).use { fileIn ->
ObjectInputStream(fileIn).use { objIn ->
@Suppress("UNCHECKED_CAST")
objIn.readObject() as? T
}
}
} catch (e: Exception) {
e.printStackTrace()
null
}
callback(result)
}
}
作为上述传统序列化方法的替代方案,可考虑使用Flatbuffers来实现灵活且高效使用内存的方法。
有关这些建议的更多详细信息和代码示例,请查看如何衡量和改进Fire OS中的应用启动时间。
内存使用方面的前台低内存终止事件
前台低内存终止事件 (LME) 指标衡量的是导致设备上应用终止的前台低内存事件的每日平均实例数。如果即使系统终止了所有非持久性后台应用或服务,仍然内存不足,就会发生前台LME。此指标有助于您了解应用遭遇严重内存限制的频率,这类限制会导致强制关闭应用。
能否尽量减少这类事件取决于应用的内存使用情况。当然,这也取决于您应用的复杂度。然而,作为一种基本基准,应尽量将游戏应用的前台内存消耗限制在1000MB以下,将非游戏应用应限制在600MB以下。过度使用内存会触发频繁的LME,这可能导致应用不稳定或崩溃,尤其是在资源有限的设备上。
有关管理应用内存的综合指南,请参阅有关减少应用内存使用量的Android开发者页面。以下策略归纳了该资源中的关键要点,帮助您减少内存使用量并提高应用的性能:
public class MainActivity extends AppCompatActivity
implements ComponentCallbacks2 {
// Other activity code.
/**
* Release memory when the UI becomes hidden or when system
* resources become low.
* @param level the memory-related event that is raised.
*/
public void onTrimMemory(int level) {
if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
// Release memory related to UI elements, such as bitmap caches.
}
if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) {
// Release memory related to background processing, such as by
// closing a database connection.
}
}
}
import android.app.Activity
import android.content.ComponentCallbacks2
import android.content.res.Configuration
import android.os.Bundle
import android.util.Log
class MainActivity : Activity(), ComponentCallbacks2 {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
registerComponentCallbacks(this)
}
override fun onTrimMemory(level: Int) {
when {
level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN -> {
// Release memory related to UI elements, such as bitmap caches
Log.d("MemoryTrim", "UI is hidden. Freeing up UI-related resources.")
}
level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND -> {
// Release memory related to background processing, such as closing a database connection
Log.d("MemoryTrim", "App in background. Releasing background resources.")
}
}
}
override fun onLowMemory() {
// Handle extreme low-memory situations
Log.w("MemoryTrim", "System is running low on memory!")
}
override fun onConfigurationChanged(newConfig: Configuration) {
// Required override but not used for memory management
}
override fun onDestroy() {
super.onDestroy()
unregisterComponentCallbacks(this)
}
}
public void doSomethingMemoryIntensive() {
// Before doing something that requires a lot of memory,
// check whether the device is in a low memory state.
ActivityManager.MemoryInfo memoryInfo = getAvailableMemory();
if (!memoryInfo.lowMemory) {
// Do memory intensive work.
}
}
// Get a MemoryInfo object for the device's current memory status.
private ActivityManager.MemoryInfo getAvailableMemory() {
ActivityManager activityManager =
(ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);
return memoryInfo;
}
import android.content.Context
fun Context.isMemoryLow(): Boolean {
val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
val memoryInfo = ActivityManager.MemoryInfo()
activityManager.getMemoryInfo(memoryInfo)
return memoryInfo.lowMemory
}
fun doSomethingMemoryIntensive(context: Context) {
if (!context.isMemoryLow()) {
// Perform memory-intensive operation
}
}
流畅度通过跟踪掉帧率来衡量动画和过渡的平滑度。此指标突显渲染过程中跳过帧的频率,这种情况会使您的应用显得不稳定,响应速度较慢。
亚马逊应用商店应用的测试标准中规定:
为了获得流畅的体验,应用的掉帧率应低于5%。掉帧率如果超过10%,会显著降低用户体验,使应用显得反应迟缓和质量低下。
要提高流畅度,应简化复杂的动画并减少同时渲染的对象数量。通过确保GPU的高效使用,以及在过渡期间最大限度减少不必要的计算,优化渲染任务。Android Studio Performance Profiler(性能分析器)中的工具Jank Detection(卡顿检测)(仅提供英文版),以及Profile GPU Rendering(GPU渲染分析)等工具可以帮助您有效地查明和解决渲染问题。
稳定性控制面板可帮助您发现和解决可能导致应用崩溃、挂起或以其他方式困扰用户的问题。通过监控数项关键指标,您可以主动提高应用的可靠性和用户体验。
崩溃率衡量应用相对于用户会话数崩溃的频率。这一指标至关重要,因为频繁的崩溃会很快导致差评和卸载。
对于良好的应用而言,崩溃率应保持在1%以下。崩溃率超过这一基准的应用存在让用户感觉不友好和降低信任度的风险。要降低崩溃率,开发者应该实施以下推荐Android开发者使用的策略:
通过系统地做到上述几点,开发者可以显著降低崩溃率,提高Fire平板电脑上应用的整体稳定性。
如果应用的主线程长时间没有响应,导致系统通知用户应用无法运行,就会发生ANR错误。这通常会导致用户强制退出您的应用。
良好的应用应达到低于0.47%的ANR率。如果比率高于上述数值,则表示您的应用可能存在性能瓶颈或主线程上的操作受到阻碍。
要解决ANR问题,请实现以下建议的修复措施:
// Bad example: Performing time-consuming task on the main thread
public void onClick(View v) {
// This will block the UI and potentially cause an ANR
Bitmap bitmap = processBitMap("image.png");
imageView.setImageBitmap(bitmap);
}
// Good example: Moving time-consuming task to a background thread
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
// A potentially time-consuming task performed off the main thread
final Bitmap bitmap = processBitMap("image.png");
// Use post() to update UI safely from the main thread
imageView.post(new Runnable() {
public void run() {
imageView.setImageBitmap(bitmap);
}
});
}
}).start();
}
import android.graphics.Bitmap
import android.os.Handler
import android.os.Looper
import android.view.View
import android.widget.ImageView
import java.util.concurrent.Executors
class MyActivity {
private val executor = Executors.newSingleThreadExecutor()
private val mainHandler = Handler(Looper.getMainLooper())
fun onClick(view: View, imageView: ImageView) {
executor.execute {
// Perform time-consuming task in background thread
val bitmap = processBitmap("image.png")
// Update UI safely on the main thread
mainHandler.post {
imageView.setImageBitmap(bitmap)
}
}
}
private fun processBitmap(filename: String): Bitmap {
// Simulate bitmap processing (e.g., decoding an image)
Thread.sleep(2000) // Simulate delay
return Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888)
}
}
除了性能和稳定性控制面板,还有其他因素需要牢记,以确保您的应用尽可能提供最佳体验:
要为Fire设备创建高质量应用需要注重性能和稳定性。借助应用运行状况洞察控制面板,开发者可以专注于关键指标,以确保自己所提供的应用具有流畅可靠的体验,让用户不断使用应用。
有兴趣进一步探索? 以下资源将在您不断提高应用质量的旅程中提供帮助: