小编Mat*_*ias的帖子

没有额外对象分配的数组/列表迭代

我正在研究用Kotlin编写的游戏,并正在研究改进GC流失.流失的主要来源之一是在主游戏/渲染循环中调用的for循环,导致迭代器的分配.

谈到文档,我发现了这一段:

数组上的for循环被编译为基于索引的循环,该循环不会创建迭代器对象.

如果要迭代数组或带索引的列表,可以这样做:

for (i in array.indices)
  print(array[i])
Run Code Online (Sandbox Code Playgroud)

请注意,这种"通过范围的迭代"被编译为最佳实现,而不创建额外的对象.

https://kotlinlang.org/docs/reference/control-flow.html#for-loops

这是真的吗?为了验证,我采用了这个简单的Kotlin程序并检查了生成的字节代码:

fun main(args: Array<String>) {
    val arr = arrayOf(1, 2, 3)
    for (i in arr.indices) {
        println(arr[i])
    }
}
Run Code Online (Sandbox Code Playgroud)

根据上面的引用,这不应该导致分配任何对象,而是编译成一个很好的旧的Java-5前样式for循环.但是,我得到的是这样的:

      41: aload_1
      42: checkcast     #23                 // class "[Ljava/lang/Object;"
      45: invokestatic  #31                 // Method kotlin/collections/ArraysKt.getIndices:([Ljava/lang/Object;)Lkotlin/ranges/IntRange;
      48: dup
      49: invokevirtual #37                 // Method kotlin/ranges/IntRange.getFirst:()I
      52: istore_2
      53: invokevirtual #40                 // Method kotlin/ranges/IntRange.getLast:()I
      56: istore_3
      57: iload_2
      58: iload_3
      59: if_icmpgt     93
Run Code Online (Sandbox Code Playgroud)

这看起来好像调用了一个调用的方法,该方法getIndices分配一个临时IntRange对象来备份此循环中的边界检查.这是一个"最佳实现","没有创建额外的对象",或者我错过了什么?

更新: 所以,经过多一点玩弄并查看答案之后,Kotlin 1.0.2似乎也是如此:

阵列:

  • for …

kotlin

34
推荐指数
2
解决办法
3万
查看次数

功能定义:fun vs val

我很好奇在Kotlin中定义成员函数的建议方法是什么.考虑这两个成员函数:

class A {

  fun f(x: Int) = 42

  val g = fun(x: Int) = 42

}
Run Code Online (Sandbox Code Playgroud)

这些似乎完成了同样的事情,但我发现了微妙的差异.

val基础的定义,举例来说,似乎是在某些情况下更加灵活.也就是说,我无法通过直接的方式f与其他功能合作,但我可以g.为了玩弄这些定义,我使用了funKTionale库.我发现这不编译:

val z = g andThen A::f // f is a member function
Run Code Online (Sandbox Code Playgroud)

但如果f被定义为val指向同一个函数,它就会编译得很好.为了弄清楚发生了什么事情,我问的IntelliJ明确定义的类型::fg对我来说,和它给了我这样的:

val fref: KFunction1<Int, Int> = ::f

val gref: (Int) -> Int = g
Run Code Online (Sandbox Code Playgroud)

所以一个是类型KFunction1<Int, Int>,另一个是类型(Int) -> Int.很容易看出它们都代表了类型的功能Int -> Int.

这两种类型有什么区别,哪些情况重要?我注意到对于顶级函数,我可以使用任何一个定义来编写它们,但是为了使前面的组合编译,我必须像这样编写它:

val z = g …
Run Code Online (Sandbox Code Playgroud)

kotlin

32
推荐指数
2
解决办法
2138
查看次数

静态引用被清除 - 如果未使用,Android会在运行时卸载类吗?

我有一个特定的问题,如何在Android中运行类加载/垃圾收集.我们现在偶然发现了几次这个问题,据我所知,Android在这里与普通的JVM不同.

问题在于:我们目前正在尝试减少应用程序中的单例类,以支持单个根工厂单例,其唯一目的是管理其他管理器类.如果你愿意的话,是一名顶级经理.这使我们可以轻松地替换测试中的实现,而无需选择完整的DI解决方案,因为所有活动和服务共享对该根工厂的相同引用.

这是它的样子:

public class RootFactory {

    private static volatile RootFactory instance;

    @SuppressWarnings("unused")
    private Context context; // I'd like to keep this for now

    private volatile LanguageSupport languageSupport;
    private volatile Preferences preferences;
    private volatile LoginManager loginManager;
    private volatile TaskManager taskManager;
    private volatile PositionProvider positionManager;
    private volatile SimpleDataStorage simpleDataStorage;

    public static RootFactory initialize(Context context) {
        instance = new RootFactory(context);
        return instance;
    }

    private RootFactory(Context context) {
        this.context = context;
    }

    public static RootFactory getInstance() {
        return instance;
    }

    public LanguageSupport getLanguageSupport() …
Run Code Online (Sandbox Code Playgroud)

java singleton android garbage-collection classloader

29
推荐指数
2
解决办法
5948
查看次数

如何跨Activity重启保留复杂对象?

假设我有一个可序列化的Java Bean对象.我想它存储起来安全当活动经过的onDestroy()的目的(即的onSaveInstanceState()是叫).

我正在寻找一种不涉及创建数据库并将对象写入其中的方法(主要是因为a)Android的DB API非常糟糕b)因为数据库使应用程序更新成为一场噩梦,因为没有适当的支持来应用迁移).

我想到将对象序列化为ByteArrayOutputStream,base64编码并将其作为字符串写入SharedPreferences文件.还是那太远了?

UPDATE

也许那个序列化到字符串的想法毕竟不是那么糟糕,似乎运作得很好.这就是我现在正在做的事情:

    public static String objectToString(Serializable object) {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    try {
        new ObjectOutputStream(out).writeObject(object);
        byte[] data = out.toByteArray();
        out.close();

        out = new ByteArrayOutputStream();
        Base64OutputStream b64 = new Base64OutputStream(out);
        b64.write(data);
        b64.close();
        out.close();

        return new String(out.toByteArray());
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

public static Object stringToObject(String encodedObject) {
    try {
        return new ObjectInputStream(new Base64InputStream(
                new ByteArrayInputStream(encodedObject.getBytes()))).readObject();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
} …
Run Code Online (Sandbox Code Playgroud)

lifecycle serialization android android-activity

22
推荐指数
1
解决办法
2万
查看次数

Amazon Web服务API是否支持条形码/ UPC查询?

我浏览了他们的文档,一开始发现它有点压倒性.我知道您可以通过输入UPC(低于1D条形码的数字)来搜索项目,但我在API中找不到关于它的单词.

我想要做的是在扫描条形码后通过执行UPC搜索来执行产品查找.

barcode amazon-web-services

20
推荐指数
2
解决办法
3万
查看次数

Android:每个应用程序对应一个HttpClient实例

直到最近,我们的应用程序在整个应用程序中使用ThreadSafeClientConnManager共享一个Apache HttpClient实例.http客户端实例由单例类保存.

由于我不喜欢单例模式存在的众多问题,我将我的API访问器重构为每线程对象,但现在对于每个线程(在我们的情况下主要是指每个Activity/Service),都会创建一个新的HttpClient实例.

这不是我对这种新方法有问题,但我已经读过Apache人员建议每个应用程序只有一个实例出于性能原因.

在视觉上,我们之前做的是:

HttpClient (thread safe)
          |
          |
         /\
        /  \
Activity1...ActivityN
Run Code Online (Sandbox Code Playgroud)

现在,我们这样做:

Activity1 ... ActivityN
    |             |
    |             |
HttpClient1   HttpClientN
Run Code Online (Sandbox Code Playgroud)

你们是如何在你的应用程序中做到这一点的?如果您在应用程序和可能有多个并发线程之间共享一个HttpClient,那么如何处理对它的访问?

concurrency singleton android

20
推荐指数
1
解决办法
5282
查看次数

如何防止ActivityUnitTestCase调用Application.onCreate?

我必须在这里遗漏一些东西.JavaDoc ActivityUnitTestCase建议此测试用例与系统隔离测试一个Activity:

此类提供单个活动的独立测试.将使用与系统基础结构的最小连接来创建测试中的活动,并且可以注入许多Activity的依赖项的模拟或包装版本.

我假设包括没有实际启动应用程序.此外,它暴露了setApplication一个可以用来注入模拟应用程序的助手.

但是,任何ActivityUnitTestCase我开始启动(实际)应用程序并调用其onCreate方法.更准确地说,InstrumentationTestRunner似乎是这样做,甚至在我有机会进入setApplication我的测试setUp方法之前就这样做了!我甚至没有注意到这一段时间,因为它似乎发生在测试套件启动期间甚至没有达到Eclipse断点的地方,但写入日志onCreate显示它实际上被调用.

这完全超出了我的范围.当Android的测试运行器实例化并执行实际应用程序时,为什么我要使用模拟应用程序对象?考虑到instrumentation runner在其自己的线程中运行,并且在执行此操作时生成主应用程序线程,这甚至更成问题.这意味着正在执行的测试和Application.onCreate被调用之间存在竞争条件.如果你在那里做任何可能影响测试的事情,例如写入共享偏好文件,那么你就完全搞砸了,因为你的测试会随机失败.

我是否遗漏了某些内容,或者这只是对测试框架的严重疏忽?

更新 这似乎ApplicationTestCase也会影响.在我的测试用例开始之前,我可以在我的应用程序类中找到一个断点onCreate.我们在那里启动了一个即发即弃的AsyncTask,它会随机失败,因为我没有机会嘲笑它(记住,之前setUp在我的测试用例中调用它).这是我在onCreate这个模糊的调用过程中看到的堆栈跟踪:

Thread [<1> main] (Suspended (breakpoint at line 86 in QypeRadar))  
QypeRadar.onCreate() line: 86   
InstrumentationTestRunner(Instrumentation).callApplicationOnCreate(Application) line: 969   
ActivityThread.handleBindApplication(ActivityThread$AppBindData) line: 4244 
ActivityThread.access$3000(ActivityThread, ActivityThread$AppBindData) line: 125    
ActivityThread$H.handleMessage(Message) line: 2071  
ActivityThread$H(Handler).dispatchMessage(Message) line: 99 
Looper.loop() line: 123 
ActivityThread.main(String[]) line: 4627    
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method] …
Run Code Online (Sandbox Code Playgroud)

android unit-testing

18
推荐指数
1
解决办法
3854
查看次数

Android自定义小部件样式:如何将它们放入命名空间?

在ApiDemos中,有一个名为Gallery1的视图示例,它在attrs.xml中声明了一个自定义样式,如下所示:

<declare-styleable name="Gallery1">
    <attr name="android:galleryItemBackground" />
</declare-styleable>
Run Code Online (Sandbox Code Playgroud)

现在,我想为我的小部件做同样的事情,但使用不同的命名空间.但是,只要我用其他东西替换android:名称空间,我就会收到此错误:

错误:在Gallery1中,无法找到属性myns:galleryItemBackground

无法找到属性?为什么它要查找我要声明的属性?这个文件的重点不是能够命名自己的自定义属性吗?

有趣的是,如果您不提供自定义命名空间,而只是提供属性名称,则它可以正常工作.

android widget

17
推荐指数
3
解决办法
1万
查看次数

sharedUserId:当应用已经上市时,可以安全地进行更改吗?

对于我们的应用程序的下一个版本,我想更改sharedUserId,因为我们现在使用内部控制仪表板应用程序,该应用程序必须写入其他应用程序的设置文件.

但由于该应用程序已安装在许多手机上,这是一个问题吗?我在模拟器上运行了一些测试,我在设备日志中看到了无法写入*.bak版本的首选项文件的例外情况.不确定是多么重要.奇怪的是,即使使用另一个Linux用户ID创建了shared_prefs文件夹,安全设置似乎仍然有效.

有没有人以前尝试过这个?

android userid sharedpreferences

17
推荐指数
1
解决办法
4880
查看次数

Activity类中的静态字段是否保证比创建/销毁周期更长?

我经常遇到一个问题,我必须在一个活动的几次调用之间保持状态(即经历几个onCreate()/ onDelete()循环).不幸的是,Android对此的支持非常糟糕.

作为一种保存状态的简单方法,我认为由于类只被类加载器加载一次,因此在静态Bundle字段中存储在活动的多个实例之间共享的临时数据是安全的.

但是,偶尔,当实例A创建静态包并在其中存储数据,然后被销毁,而实例B尝试从中读取时,静态字段突然变为NULL.

这是否意味着当活动进行创建/销毁循环时,类已被类加载器删除并重新加载?在以前引用对象时,静态字段怎么会突然变为NULL?

java static android classloader

16
推荐指数
1
解决办法
8407
查看次数