应用程序安装大小在手机上有何不同?

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/packagels -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 成员泄漏MainActivitys,然后再担心性能 我的印象是静态成员只允许一个实例,因此不会导致太多泄漏。请原谅我对这个问题的无知。我正在努力学习。 @Torcellite 不用担心,我们都只是想学习 :) 只是指出我希望这个答案能满足你最初的问题,关于 static 我建议你阅读一些关于它的东西,我喜欢 Head First 系列,他们恰好有一本很不错的书,名为 Head First Java 感谢您的推荐,感谢您不厌其烦地进行研究。 :) 我希望赏金能够运行它,看看是否会弹出任何不同的答案。如果没有,我会奖励给你。

以上是关于应用程序安装大小在手机上有何不同?的主要内容,如果未能解决你的问题,请参考以下文章

Android应用程序包在手机上安装在哪里

如果从浏览器安装在手机上,如何导航移动应用程序

尝试在手机上安装 app_debug.apk 并获取未安装的应用程序

如何通过网站链接在手机上打开应用程序

Android studio安装APK在手机上但无法找到该应用程序

python代码怎么在手机上运行