我一直在阅读一些有关Android内存泄漏的文章,并观看了Google I/O 关于此主题的有趣视频.
尽管如此,我还是不完全理解这个概念,特别是当在Activity中使用内部类是安全或危险的时候.
这就是我的理解:
如果内部类的实例比其外部类(活动)存活的时间更长,则会发生内存泄漏.- > 在哪种情况下会发生这种情况?
在这个例子中,我认为没有泄漏的风险,因为匿名类扩展没有办法OnClickListener比活动更长寿,对吧?
final Dialog dialog = new Dialog(this);
dialog.setContentView(R.layout.dialog_generic);
Button okButton = (Button) dialog.findViewById(R.id.dialog_button_ok);
TextView titleTv = (TextView) dialog.findViewById(R.id.dialog_generic_title);
// *** Handle button click
okButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
dialog.dismiss();
}
});
titleTv.setText("dialog title");
dialog.show();
Run Code Online (Sandbox Code Playgroud)
现在,这个例子是危险的,为什么?
// We are still inside an Activity
_handlerToDelayDroidMove = new Handler();
_handlerToDelayDroidMove.postDelayed(_droidPlayRunnable, 10000);
private Runnable _droidPlayRunnable = new Runnable() {
public void run() {
_someFieldOfTheActivity.performLongCalculation(); …Run Code Online (Sandbox Code Playgroud) String s = "hello";
String backup_of_s = s;
s = "bye";
Run Code Online (Sandbox Code Playgroud)
此时,备份变量仍然包含原始值"hello"(这是因为String的不变性吗?).
但是使用这种方法复制字符串是否真的安全(复制常规可变对象当然不安全),或者写这个更好?:
String s = "hello";
String backup_of_s = new String(s);
s = "bye";
Run Code Online (Sandbox Code Playgroud)
换句话说,这两个片段之间有什么区别(如果有的话)?
编辑 - 第一个片段安全的原因:
让我根据已经提供的好答案(主要关注两个片段之间的性能差异问题),更详细地解释一下事情:
字符串在Java中是不可变的,这意味着String对象在构造后不能被修改.因此,
String s = "hello";创建一个新的String实例并将其地址分配给s(s作为对实例/对象的引用)
String backup_of_s = s;创建一个新变量backup_of_s并初始化它,以便它引用当前引用的对象s.
注意:字符串不变性保证不会修改此对象:我们的备份是安全的
注2:Java垃圾收集机制保证只要至少有一个变量(backup_of_s在这种情况下)引用该对象,就不会销毁该对象
最后,s = "bye";创建另一个String实例(由于不变性,这是唯一的方法),并修改s变量,使其现在引用新对象.
当用户处于无信号区域或手机处于飞行模式时,我想测试我的应用程序的行为.
- > 如何将Android虚拟设备置于离线模式(无法连接到互联网)?
我尝试过以下方法:
通过AVD设置激活飞行模式:令人惊讶的是,这不起作用(在飞行模式下仍然可以浏览互联网!)
在我的电脑上禁用网络连接:这显然有效,但由于我在测试我的应用时需要互联网,因此效果不理想
我已按照本指南在Android Studio v1.4中为我的主要Android模块创建一个JUnit测试文件(我们称之为"module-a").
我的"module-a"依赖于作为.aar文件提供的外部库,我必须为其创建一个专用模块.
此依赖项会导致错误:
右键单击测试Java文件并点击"运行MyTestName"时,它将失败并显示此错误
Error:Gradle:
FAILURE: Build failed with an exception.
* What went wrong:
Task 'testClasses' not found in project ':module-b'.
Run Code Online (Sandbox Code Playgroud)
删除对module-b的依赖性可以解决问题.
模块的摘录 - build.gradle:
compile project(':module-b')
Run Code Online (Sandbox Code Playgroud)
module-b build.gradle:
configurations.create("default")
artifacts.add("default", file('library-b.aar'))
Run Code Online (Sandbox Code Playgroud)
我应该如何配置Gradle以便它不会尝试testClasses在"module-b"上运行任务?(这应该解决我的问题)
Google Play商店支持(自2012年8月起)一项名为Smart App Updates的新功能,该功能允许在升级应用时仅下载必要的"增量".
我没有找到开发人员关于此功能的文档,因此我不知道如何优化我的应用程序以确保它从这个伟大的机制中受益.
那么,有谁知道:
asset夹中的文件一样)自2014年11月21日起,我收到了数百份崩溃报告,其中包含以下堆栈.
崩溃仅发生在API Level 10设备上(该应用程序支持9+)
在崩溃开始前的几个星期内,该应用程序的相同版本运行良好.这让我觉得问题是由最近推送到Android 2.3设备的一些无线更新引起的.
我在我的应用中使用AdMob中介(现在是Google Play服务库的一部分)和其他几个广告网络SDK.
我怀疑Google Play服务库会导致崩溃,因为根据我的知识,它是应用程序中唯一可能通过无线更新的部分(这不是第一次更新错误导致崩溃).
正如OP 在这里回答的那样,是否有可能在AdMob创建的用于显示横幅广告的线程内触发的未捕获异常可能会使整个过程处于无法再创建新类实例的状态?
最近有没有人遇到过类似的问题?
java.lang.NoClassDefFoundError: com.myapp.MyClassExtendingAsyncTask
at com.myapp.x.run(SourceFile:417)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3859)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:647)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.ClassNotFoundException: com.myapp.MyClassExtendingAsyncTask in loader dalvik.system.PathClassLoader[/data/app/com.myapp-1.apk]
at dalvik.system.PathClassLoader.findClass(PathClassLoader.java:240)
at java.lang.ClassLoader.loadClass(ClassLoader.java:551)
at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
... 10 more
Run Code Online (Sandbox Code Playgroud) 我的应用程序的下一个版本大约有70K方法.
了解使用Multidex的确切含义(通常意味着使用Multidex支持库来支持API <21)对我做出这个决定非常重要:
我应该付出很多努力(例如通过微调我的Proguard配置以更积极地缩小,倾倒一些第三方库等)以符合64K方法限制,或者我应该只启用Multidex?
该文件表明,Multidex支持库可能有一些严重的副作用(见Limitations of the multidex support library).
我真的应该期待什么?
我们将非常感谢您自己迁移到Multidex的反馈.
在我的应用程序的第一次运行,我正在下载一个非常大的文件到/ sdcard /
我已经知道如果用户手机的内部SD卡已满或未安装(例如,如果手机作为大容量存储设备连接到PC,或者未正确断开与PC的连接),则可能会失败.
但是有没有没有内部SD卡的Android设备?(我的应用肯定无法使用)
我正在使用Eclipse开发Android棋盘游戏.我在Android项目中开发了UI.
另一方面,我在常规Java项目中开发了AI,因为我希望能够在没有Android模拟器的所有约束的情况下测试它(我没有找到使用我的Windows JVM运行代码的任何其他方法).
现在,我希望"加入"两个项目(独立工作正常),即使用UI中的AI Java类.
这是我尝试过的:
在我的Android项目Properties > Projects References中,我勾选了Java项目.这允许我构建没有错误的Android项目(实例化AI对象).
但它在运行时因此错误而失败:
Could not find class 'my.package.AI', referenced from method my.otherpackage.UI.onStart
Run Code Online (Sandbox Code Playgroud)
将AI Java项目纳入我的Android项目的正确方法是什么?
(注意:我仍然希望能够开发和测试AI作为常规Java应用程序,因此我认为使用jar或将所有源代码复制到Android项目将不适合我的需求)
编辑:
我希望新的ADT v17可以解决问题,但事实并非如此.我几乎尝试了所有可用的选项,在我的Android项目中包含一个项目:
允许编译和运行而没有错误的唯一方法是将Java项目的JAR添加到Android项目构建路径.
我正在游戏中实现自定义可扩展操作栏.我正在使用ViewDragHelper来处理条形视图的拖动和拖动,它包含在LinearLayoutI子类中以附加ViewDragHelper.
以下链接对实现此目的有很大帮助:
我遇到的唯一问题是我的父LinearLayout 的layout()的行为:在每次调用layout()/时onLayout(),子draggable/expandable操作栏被重置为其原始位置(XML布局中设置的位置).
这是为什么 ?
(根据我的经验,layout()从未对已被移动的观点的位置感到困惑)