profile
viewpoint

NightlyNexus/DemoMode 19

Control Android's Demo Mode from your app.

NightlyNexus/Color-Clock 10

An Android TextClock widget with a user-defined color

NightlyNexus/AndyPedia 3

A Better Wikipedia Android App

NightlyNexus/cardslib 3

Android Library to build a UI Card

NightlyNexus/android_device_zte_roamer2 2

Porting CyanogenMod to the ZTE Open

NightlyNexus/blog.nightlynexus.com 1

http://blog.nightlynexus.com

NightlyNexus/conferences 1

A community-curated list of conferences around the world for Android developers.

NightlyNexus/Crashes-to-Drive 1

Log crashes to any service that connects to IFTTT.

NightlyNexus/AdAway 0

AdAway is an open source ad blocker for Android using the hosts file.

NightlyNexus/analytics-android 0

The hassle-free way to add analytics to your Android app.

issue openedsquare/moshi

How to parse fields with the same key but different values

This is driving me crazy. I spent the whole day and I still cannot figure out the issue I'm facing.

Our backend sends a json response that can contain different values for the same key every time.

Example of First variation:

{
  "title": "2",
  "profile_image": {
    "profile_image_id": "4581542",
    "sized": "media/up/2020/48/460e689e286ca46b1006b62269ee21a22b6bdabf2496506e34e5d07c5d42c20f_user_photo_160674563705555.sized.JPG",
    "sized_w": "556",
    "sized_h": "555",
    "thumb": "media/up/2020/48/460e689e286ca46b1006b62269ee21a22b6bdabf2496506e34e5d07c5d42c20f_user_photo_160674563705555.thumb.JPG",
    "thumb_w": "90",
    "thumb_h": "90"
  },
  "profile": {
    "title": "2",
    "first_name": "John",
    "last_name": "Doe",
    "user_online_status": false
  }
}

And below is an another variation of the same response. Notice the profile_image field is now an Array type and user_online_status can also be a string or a boolean.

{
  "title": "2",
  "profile_image": [
    
  ],
  "profile": {
    "title": "2",
    "first_name": "John",
    "last_name": "Doe",
    "user_online_status": "0"
  }
}

How can I parse such responses using Retrofit and Moshi without creating extra model classes? Can I use a custom adapter Maybe? Could you give me an example? I tried to make an adapter of my own but didn't managed to get far

class SkipEmptyProfileAdapter {
    

    @FromJson
    fun fromJson(reader: JsonReader): UserProfileDataResponse? {
        val moshi = Moshi.Builder().build()

        reader.beginObject()
        while (reader.hasNext()) {
            if (reader.nextName() == "profile_image") {
                Timber.i("PROFILE IMAGE")
                val pls = reader.peek()
                if (pls == JsonReader.Token.BEGIN_ARRAY)
                    return null
            }
        }
        reader.endObject()
        return null
    }

}

Can you help me out?

created time in 14 minutes

issue closedsquare/kotlinpoet

How to judge whether the parameter of annotation is nullable?

val isNullable = parameterElement.asType().asTypeName().isNullable

When I do, it always returns null

closed time in 41 minutes

plumcookingwine

delete branch google/error-prone

delete branch : test_344901421

delete time in 44 minutes

PR merged google/error-prone

Introduce GitHub Actions based CI workflow cla: yes

Introduce GitHub Actions based CI workflow

+86 -0

0 comment

1 changed file

copybara-service[bot]

pr closed time in 44 minutes

push eventgoogle/error-prone

Liam Miller-Cushon

commit sha 745c3c7537ff0f13a3090c12ad5375ca9eb434f9

Introduce GitHub Actions based CI workflow PiperOrigin-RevId: 344921997

view details

push time in 44 minutes

push eventgoogle/error-prone

Liam Miller-Cushon

commit sha 745c3c7537ff0f13a3090c12ad5375ca9eb434f9

Introduce GitHub Actions based CI workflow PiperOrigin-RevId: 344921997

view details

push time in 44 minutes

issue openedsquare/kotlinpoet

How to judge whether the parameter of annotation is nullable?

val isNullable = parameterElement.asType().asTypeName().isNullable

When I do, it always returns null

created time in an hour

PR opened google/error-prone

Delete travis and appveyor configs

Delete travis and appveyor configs

and add Github Actions as a Copybara presubmit.

+0 -68

0 comment

1 changed file

pr created time in an hour

create barnchgoogle/error-prone

branch : test_344887123

created branch time in an hour

PR opened google/error-prone

Introduce GitHub Actions based CI workflow

Introduce GitHub Actions based CI workflow

+86 -0

0 comment

1 changed file

pr created time in an hour

create barnchgoogle/error-prone

branch : test_344901421

created branch time in an hour

push eventgoogle/dagger

travis-ci

commit sha 0f5acae4f4743a1019e2bc8b8425d3e274fcb81b

Latest javadoc on successful travis build 1939 auto-pushed to gh-pages

view details

push time in an hour

Pull request review commentcashapp/misk

Support deliveryDelay and processing of individual jobs by FakeJobQueue

 internal class FakeJobQueueTest {     assertThat(fakeJobQueue.peekJobs(GREEN_QUEUE)).isEmpty()     assertThat(fakeJobQueue.peekJobs(RED_QUEUE)).isEmpty()   }++  @Test+  fun considerDeliveryDelaysInFakeJob() {

Broke down on three tests: jobsDoNotStartUntilDeliveryDelayElapses jobsStartOnDeliveryDelayPassed jobsStartAfterDeliveryDelayPassed

alatyshau

comment created time in 2 hours

issue openedKotlin/kotlinx.coroutines

[guava] JobListenableFuture.isCancelled() throws if future is completed exceptionally

The bug was introduced in #2222

    @Test
    fun testFailedFuture_isCancelledDoesNotThrow() = runTest {
        val future = future(context = NonCancellable) {
            throw TestException()
        }
        yield()
        assertTrue(future.isDone)
        assertFalse(future.isCancelled)  // throws ExecutionException here.
        val thrown = assertFailsWith<ExecutionException> { future.get() }
        assertTrue(thrown.cause is TestException)
    }

Uninteraptables.getUninterruptibly(future) throws ExecutionException if the future is completed exceptionally.

created time in 2 hours

push eventgoogle/dagger

Dagger Team

commit sha 06caf17d71f8efd72e86506af12256317af36f58

Roll forward with fix of 'Migrating @ViewModelInject into Hilt's codebase'. Additional changes compared to the original CL: * An additional Module per @ViewModelInject-annotated ViewModel class will be created to bind the class name to a Set<String>. * The Set<String> of injected view models class names will be used by the HiltViewModelFactory to determine whether the view model to create should come from the ViewModelComponent or not. By filtering out non-injected view models the factory can avoid eagerly creating a SavedStateHandle for a view model that will not be created via the ViewModelComponent. PiperOrigin-RevId: 344909991

view details

push time in 2 hours

PR closed google/dagger

Roll forward with fix of 'Migrating @ViewModelInject into Hilt's codebase'. cla: yes

Roll forward with fix of 'Migrating @ViewModelInject into Hilt's codebase'.

Additional changes compared to the original CL:

  • An additional Module per @ViewModelInject-annotated ViewModel class will be created to bind the class name to a Set<String>.
  • The Set<String> of injected view models class names will be used by the HiltViewModelFactory to determine whether the view model to create should come from the ViewModelComponent or not.

By filtering out non-injected view models the factory can avoid eagerly creating a SavedStateHandle for a view model that will not be created via the ViewModelComponent.

+2416 -4

0 comment

44 changed files

copybara-service[bot]

pr closed time in 2 hours

push eventgoogle/dagger

Dagger Team

commit sha 06caf17d71f8efd72e86506af12256317af36f58

Roll forward with fix of 'Migrating @ViewModelInject into Hilt's codebase'. Additional changes compared to the original CL: * An additional Module per @ViewModelInject-annotated ViewModel class will be created to bind the class name to a Set<String>. * The Set<String> of injected view models class names will be used by the HiltViewModelFactory to determine whether the view model to create should come from the ViewModelComponent or not. By filtering out non-injected view models the factory can avoid eagerly creating a SavedStateHandle for a view model that will not be created via the ViewModelComponent. PiperOrigin-RevId: 344909991

view details

push time in 2 hours

delete branch google/dagger

delete branch : test_343220209

delete time in 2 hours

issue commentgoogle/dagger

Hilt - PreferenceFragmentCompat Support

@FunkyMuse if you move your SettingsFragment into a module different from app it will probably fail.

epool

comment created time in 3 hours

push eventgoogle/dagger

Dagger Team

commit sha f38eb1c1e28973e05af8b62e6525daf0d465778b

Roll forward with fix of 'Migrating @ViewModelInject into Hilt's codebase'. Additional changes compared to the original CL: * An additional Module per @ViewModelInject-annotated ViewModel class will be created to bind the class name to a Set<String>. * The Set<String> of injected view models class names will be used by the HiltViewModelFactory to determine whether the view model to create should come from the ViewModelComponent or not. By filtering out non-injected view models the factory can avoid eagerly creating a SavedStateHandle for a view model that will not be created via the ViewModelComponent. PiperOrigin-RevId: 343220209

view details

push time in 3 hours

Pull request review commentcashapp/misk

Support deliveryDelay and processing of individual jobs by FakeJobQueue

 data class FakeJob(   override fun deadLetter() {     deadLettered = true   }++  override fun equals(other: Any?): Boolean {

(Dropped my previous comments: nevermind) The only place where it was critical is when we find and remove, and this would be the same instance. So even if FakeJob was concurrently modified (it has two vars), the instance would be the same.. I have just overthought this.. So Im rolling this back.

alatyshau

comment created time in 3 hours

Pull request review commentcashapp/misk

Support deliveryDelay and processing of individual jobs by FakeJobQueue

 data class FakeJob(   override fun deadLetter() {     deadLettered = true   }++  override fun equals(other: Any?): Boolean {

Or should I better make FakeJob not a data class: class FakeJob( and then skip overriding hashCode/equals?

alatyshau

comment created time in 3 hours

Pull request review commentcashapp/misk

Support deliveryDelay and processing of individual jobs by FakeJobQueue

 data class FakeJob(   override fun deadLetter() {     deadLettered = true   }++  override fun equals(other: Any?): Boolean {

So equals and hashCode become:



  override fun equals(other: Any?): Boolean {
    return this === other
  }

  override fun hashCode(): Int {
    return System.identityHashCode(this)
  }

Does this look good?

alatyshau

comment created time in 3 hours

Pull request review commentcashapp/misk

Support deliveryDelay and processing of individual jobs by FakeJobQueue

 class FakeJobQueue @Inject constructor(   fun handleJobs(     queueName: QueueName,     assertAcknowledged: Boolean = true,-    retries: Int = 1+    retries: Int = 1,+    considerDelays: Boolean = false

This will very probably break a bunch of tests in Franklin :)) It is better to do in a separate PR:

  1. Introduce an option in FakeJobQueueModule
  2. Use this option in all services and fix the tests
  3. Then make this option default
alatyshau

comment created time in 3 hours

Pull request review commentcashapp/misk

Support deliveryDelay and processing of individual jobs by FakeJobQueue

 class FakeJobQueue @Inject constructor(       }     } +    // Reenqueue deadlettered jobs outside of the main loop to prevent an infinite loop.     result.forEach { job ->       if (job.deadLettered) {-        deadletteredJobs.getOrPut(queueName, ::ConcurrentLinkedDeque).add(job)+        deadletteredJobs.getOrPut(job.queueName, ::ConcurrentLinkedDeque).add(job)       }     }-     return result   }++  private fun pollNextJob(jobs: Queue<FakeJob>, considerDelays: Boolean): FakeJob? {+    if (!considerDelays) {+      return jobs.poll()+    }+    val now = clock.instant()!!+    while (true) {+      val job = jobs.firstOrNull {

You right, since queue is sorted by deliveryAt, using peek() will work here. I will fix that. In my first version I reused ConcurrentLinkedDeque which was not sorted by deliveryAt, and later fixed to PriorityBlockingQueue. I will also then make sure that dead letter queue never uses this branch (it is still on ConcurrentLinkedDeque)

alatyshau

comment created time in 3 hours

Pull request review commentcashapp/misk

Support deliveryDelay and processing of individual jobs by FakeJobQueue

 class FakeJobQueue @Inject constructor(       }     } +    // Reenqueue deadlettered jobs outside of the main loop to prevent an infinite loop.     result.forEach { job ->       if (job.deadLettered) {-        deadletteredJobs.getOrPut(queueName, ::ConcurrentLinkedDeque).add(job)+        deadletteredJobs.getOrPut(job.queueName, ::ConcurrentLinkedDeque).add(job)       }     }-     return result   }++  private fun pollNextJob(jobs: Queue<FakeJob>, considerDelays: Boolean): FakeJob? {+    if (!considerDelays) {+      return jobs.poll()+    }+    val now = clock.instant()!!+    while (true) {+      val job = jobs.firstOrNull {+        it.deliveryDelay == null || !it.enqueuedAt.plus(it.deliveryDelay).isAfter(now)+      }+      // If remove() is false, then we lost race to another worker and should retry.

I think tests should avoid using concurrency at all, because it is not deterministic. But then I'd replace ConcurrentHashMap by usual HashMap, etc. Otherwise using ConcurrentHashMap and then not caring about the rest is confusing. Can I remove all concurrency related stuff from this class? :)

alatyshau

comment created time in 3 hours

Pull request review commentcashapp/misk

Support deliveryDelay and processing of individual jobs by FakeJobQueue

 data class FakeJob(   override fun deadLetter() {     deadLettered = true   }++  override fun equals(other: Any?): Boolean {

The reason I added this override are two vars:

  var acknowledged: Boolean = false
  var deadLettered: Boolean = false

FakeJob is used in queue.remove() so this is important. Well, we basically don't use FakeJobQueue in tests with concurrency involved, so I'd not care, but misk is a very shared library and it uses ConcurrentHashMap etc., so to stay multi-thread safe, we need this override here.

But I can include more immutable fields: all of vals. Would that work?

alatyshau

comment created time in 3 hours

issue openedKotlin/kotlinx.serialization

[Help] How to deserialize/parse lists after 1.0?

I used to use A.serializer().list to get a list serializer, but this extension is removed after 1.0. Is there a replacement?

Answers in this issue are deprecated: https://github.com/Kotlin/kotlinx.serialization/issues/179

created time in 4 hours

Pull request review commentcashapp/misk

Support deliveryDelay and processing of individual jobs by FakeJobQueue

 data class FakeJob(   override fun deadLetter() {     deadLettered = true   }++  override fun equals(other: Any?): Boolean {+    if (this === other) return true+    if (javaClass != other?.javaClass) return false++    other as FakeJob++    if (id != other.id) return false++    return true+  }++  override fun hashCode(): Int {

(and this too)

alatyshau

comment created time in 4 hours

Pull request review commentcashapp/misk

Support deliveryDelay and processing of individual jobs by FakeJobQueue

 class FakeJobQueue @Inject constructor(       }     } +    // Reenqueue deadlettered jobs outside of the main loop to prevent an infinite loop.     result.forEach { job ->       if (job.deadLettered) {-        deadletteredJobs.getOrPut(queueName, ::ConcurrentLinkedDeque).add(job)+        deadletteredJobs.getOrPut(job.queueName, ::ConcurrentLinkedDeque).add(job)       }     }-     return result   }++  private fun pollNextJob(jobs: Queue<FakeJob>, considerDelays: Boolean): FakeJob? {+    if (!considerDelays) {+      return jobs.poll()+    }+    val now = clock.instant()!!+    while (true) {+      val job = jobs.firstOrNull {+        it.deliveryDelay == null || !it.enqueuedAt.plus(it.deliveryDelay).isAfter(now)+      }+      // If remove() is false, then we lost race to another worker and should retry.

Callers probably shouldn’t be doing this concurrently?

alatyshau

comment created time in 4 hours

more