应用程序安装大小在手机上有何不同?
Posted
技术标签:
【中文标题】应用程序安装大小在手机上有何不同?【英文标题】:How does application install size vary on phone? 【发布时间】:2013-07-12 14:26:23 【问题描述】:我最近为经常修改设备的 root 用户制作了这个 application。
现在我注意到应用程序的安装大小出现了非常奇怪的行为。
当我使用从 XML 文件初始化视图的常规活动时,大小为 715 kb
。
@Override
protected void onCreate(Bundle bundle)
super.onCreate(bundle);
setContentView(R.layout.main_layout);
executeEvents = new ExecuteEvents(this);
display = (TextView) findViewById(R.id.display);
powermenu = (Button) findViewById(R.id.powermenu);
turnoffscreen = (Button) findViewById(R.id.turnscreenoff);
mapButton = (ImageButton) findViewById(R.id.mapButton);
SP = getSharedPreferences(PBConstants.Power_Button_SP, MODE_MULTI_PROCESS);
if(SP.contains(PBConstants.INPUT_DEVICE_TAG))
display.setText(getResources().getString(R.string.configured));
mapButton.setOnClickListener(this);
powermenu.setOnClickListener(this);
turnoffscreen.setOnClickListener(this);
在我切换到一个创建的对话框后,该对话框设置了一个包含 XML 文件中的小部件的视图。应用大小现在为200kb
。
@Override
protected void onCreate(Bundle bundle)
super.onCreate(bundle);
//setContentView(R.layout.main_layout);
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.main_layout, null);
executeEvents = new ExecuteEvents(this);
display = (TextView) view.findViewById(R.id.display);
powermenu = (Button) view.findViewById(R.id.powermenu);
turnoffscreen = (Button) view.findViewById(R.id.turnscreenoff);
mapButton = (ImageButton) view.findViewById(R.id.mapButton);
SP = getSharedPreferences(PBConstants.Power_Button_SP, MODE_MULTI_PROCESS);
if(SP.contains(PBConstants.INPUT_DEVICE_TAG))
display.setText(getResources().getString(R.string.configured));
mapButton.setOnClickListener(this);
powermenu.setOnClickListener(this);
turnoffscreen.setOnClickListener(this);
Dialog dialog = new Dialog(this);
dialog.setContentView(view);
dialog.setTitle(getResources().getString(R.string.app_name));
dialog.show();
当我使用这个时它减少到80kb
:
@Override
protected void onCreate(Bundle bundle)
super.onCreate(bundle);
dialog = new Dialog(this);
dialog.setContentView(R.layout.main_layout);
executeEvents = new ExecuteEvents(this);
display = (TextView) dialog.findViewById(R.id.display);
powermenu = (Button) dialog.findViewById(R.id.powermenu);
turnoffscreen = (Button) dialog.findViewById(R.id.turnscreenoff);
mapButton = (ImageButton) dialog.findViewById(R.id.mapButton);
SP = getSharedPreferences(PBConstants.Power_Button_SP, MODE_MULTI_PROCESS);
if(SP.contains(PBConstants.INPUT_DEVICE_TAG))
display.setText(getString(R.string.configured));
mapButton.setOnClickListener(this);
powermenu.setOnClickListener(this);
turnoffscreen.setOnClickListener(this);
dialog.setTitle(getString(R.string.app_name));
dialog.show();
dialog.setOnDismissListener(new DialogInterface.OnDismissListener()
@Override
public void onDismiss(DialogInterface dialogInterface)
dialog.dismiss();
MainActivity.this.finish();
);
当我尝试使用最后一种代码样式(80kb
)添加动画时,我还注意到应用程序大小的另一个奇怪变化。应用程序大小变得很大1 MB
。这就是我初始化动画并尝试在单击按钮时调用它的方式:
private static final ScaleAnimation animation = new ScaleAnimation(1, .95f, 1, .95f, Animation.RELATIVE_TO_SELF, (float)0.5, Animation.RELATIVE_TO_SELF, (float)0.5);//declared as global variable
onCreate 方法内部:
animation.setDuration(1000);
animation.setFillAfter(false);
之后我在onClickListener
中调用它:
mapButton.startAnimation(animation);
为什么在我没有添加任何新资源而只是更改代码样式的情况下,应用程序大小会发生如此剧烈的变化?我初始化对话框中出现的小部件的方式哪里有这么大的不同?为什么以我添加动画的方式添加动画会有很大的不同?
后续问题:
@Override
protected void onCreate(Bundle bundle)
super.onCreate(bundle);
setContentView(R.layout.main_layout);
executeEvents = new ExecuteEvents(this);
display = (TextView) this.findViewById(R.id.display);
powermenu = (Button) this.findViewById(R.id.powermenu);
turnoffscreen = (Button) this.findViewById(R.id.turnscreenoff);
mapButton = (ImageButton) this.findViewById(R.id.mapButton);
SP = getSharedPreferences(PBConstants.Power_Button_SP, MODE_MULTI_PROCESS);
if(SP.contains(PBConstants.INPUT_DEVICE_TAG))
display.setText(getResources().getString(R.string.configured));
mapButton.setOnClickListener(this);
powermenu.setOnClickListener(this);
turnoffscreen.setOnClickListener(this);
推测
这可能是由于导入了包或类吗?至少对于问题的animation
位是有意义的。
添加视图初始化的上下文会减少内存使用吗?
【问题讨论】:
您可以解压 APK 并分析其组件。您还可以剖析 dex 文件 (code.google.com/p/smali) 以查看其结构。 APK 大小相同。安装尺寸不同。 哇,这很有趣。不过,在有根设备上,您可以分析与已安装应用程序相关的单个文件。比如ls -l /data/app/package
、ls -l /data/data/package
。
【参考方案1】:
是的,您的推测几乎是正确的,因此您可能知道您的所有 Java 代码首先通过 javac
编译为 Java 字节码,然后dx
将它们转换为 Dalvik 字节码,即您的 dalvik 字节码文件(a.k.a. dex
) 被打包在您的 apk 中(顺便说一句,apk 大小变化不大,因为 zip 压缩有帮助)通常为 classes.dex
,稍后当您在您的设备中安装 apk 时,android 可能会针对该特定设备优化它(a.k.a. odex
)。
因此,要验证您最终缓存的 dex
是否确实发生了变化,并且是造成这种大小变化的原因,比如添加动画,您可以通过解压缩 apk 或在设备中找到它,我总是找到第二个选项更精彩:
这里是你的dex
,没有动画(你的80kb
):
还有你的应用信息:
这里是你的dex
动画(你的1 MB
):
还有你的应用信息:
只要在你的 dalvik 字节码常量池中仔细观察,你就会发现它们确实不同:
由于某种原因,我没有得到如此巨大的大小差异,但很明显,我使用 gradle + Android Studio 构建了您的应用程序,所以我认为它们有助于并优化了一些东西。
最后,您可以使用 ProGuard,但是,嘿!现在有些 k 并没有那么多,我不会担心在你的应用程序中添加一些“胖”,只要它能让它变得更好,当然总是有改进的余地,但请记住你不是在 java4k 或其他东西像这样:)
【讨论】:
当您执行这些更改时,应用程序的性能是否会因实施方式的不同而不同? @Torcellite 这是另一个问题,我想说你应该首先担心与所有static
成员泄漏MainActivity
s,然后再担心性能
我的印象是静态成员只允许一个实例,因此不会导致太多泄漏。请原谅我对这个问题的无知。我正在努力学习。
@Torcellite 不用担心,我们都只是想学习 :) 只是指出我希望这个答案能满足你最初的问题,关于 static
我建议你阅读一些关于它的东西,我喜欢 Head First 系列,他们恰好有一本很不错的书,名为 Head First Java
感谢您的推荐,感谢您不厌其烦地进行研究。 :) 我希望赏金能够运行它,看看是否会弹出任何不同的答案。如果没有,我会奖励给你。以上是关于应用程序安装大小在手机上有何不同?的主要内容,如果未能解决你的问题,请参考以下文章
尝试在手机上安装 app_debug.apk 并获取未安装的应用程序