Divyansh Kushwaha’s GSoC 2022 Report

divyanshdxn
5 min readOct 6, 2022

--

Name: Divyansh Kushwaha
Organization: AnkiDroid
Proposal: Divyansh’s GSoC Proposal
Objective: AsyncTask to Coroutines Migration Issue #7108

Hi! I am Divyansh, and I’ve finally completed my Google Summer of Code 2022 project under the mentorship of the organization AnkiDroid

What is AnkiDroid?

AnkiDroid is an Android companion app for Anki, a flashcards application that helps people learn and memorize a diverse variety of topics.

AnkiDroid: Anki flashcards on Android. Your secret trick to achieve superhuman information retention.

The first interaction with maintainers

My first interaction with a maintainer happened accidentally. I was working for a startup that used a fork of AnkiDroid as the base of their project. I had to remove the sync feature from the existing fork and I mistakenly made a pull request to the main AnkiDroid repo 😆(kind of felt funny, but yeah this was it). So my first PR was an accidental one and was closed unmerged. David Allison was the first to comment on that and asked me to share a link to the project, so I joined the discord server. And that was the beginning of me starting my contribution to AnkiDroid. There I saw a separate channel for GSoC, and since I was looking to apply for it I started asking questions on the server and found the community very welcoming and helpful. From there my journey to open-source contributions began.

Initial Contributions

After joining the discord server, I came to know that there is something called good first issues which is for newcomers to get familiar with and start their contributions. During that time, AnkiDroid was going through Java to Kotlin migrations. There were some changes that would reduce and simplify code using Koltin features, such changes were marked as KotlinCleanup. Before starting GSoC I started with these cleanup tasks. And eventually started working on the migration of startActivityForResult to newer APIs. Done a few KotlinMigrations myself as well.

Objective

AnkiDroid was initially built on Java and used AsyncTask to handle asynchronous operations. Since AsyncTask is deprecated and AnkiDroid was already migrating to Kotlin, the asynchronous operations such as network calls, database access, etc can be moved to Kotlin Coroutines. I already wanted to learn more about concurrency and parallelism concepts.

So, the Migration from AsyncTask to Coroutines was the objective of my GSoC project.

Application for GSoC

After choosing the GSoC topic and getting familiar with the codebase, it was time to prepare my proposal. For that, I really needed to put together strategies that I could use to do the migration. After going through these all, I did a sample migration just to show what the actual project might look like. I wrote the Application from the standard template that was provided by the organization only. I asked for a review of my Application by maintainers and received a lot of them. It went through 3–4 rounds of review till I finally submitted my proposal.

Community Bonding Period

It is the initial time that Google gives to involve in the community activities that happened within an organization. Since I already had been contributing and knew the community it went very well, even though I started my coding in this period. I had a video call meet together with the other community members and my fellow GSoC students as well. It was a fun session and we shared our journey and experiences with the community so far.

Coding Period

The first thing to do before starting the migration to Coroutines is to migrate required classes from Java to Kotlin because coroutines are a Kotlin feature. During the first week, I worked on migrating existing Java files that contain AsyncTask codes to Kotlin. I utilized my this time well by doing many Kotlin migrations. Thanks to the automated script that we have in AnkiDroid which made this process a lot easier. For migration to Kotlin, we followed a specific set of rules to make sure nothing breaks and the transition is smooth (like avoiding functional changes). More detailed documentation is written by community members which can be found here.

For the coroutines, my initial plan was to create a base wrapper class similar to AsyncTask but instead of using underlying raw threads I would use suspend functions for the callbacks. I thought that migration should be done without changing the already existing architecture, like a patch on existing code but after discussing with the mentors and other community members I came to a conclusion to follow a different approach. Most of the architecture was laid down to handle cancellations and memory leaks due to AsyncTask which we do not need to worry about when using Coroutines. Using the right CoroutineScopes and bounding the coroutines to a LifecycleOwner handle these two very well, so we do not have to worry about checking if the UI is still alive or not.

Following a strategy, the doInBackground callback of AsyncTask would be replaced by a suspend function performing the same operation. And onPreExecute and onPostExecute callbacks would be called as it is before and after calling the suspend function. Using this concept, I started migrating firstly with the independent classes, and later when I became much more familiar with the codebase I started migrating the core part of the codebase.

List of merged PRs in which I’ve done the migrations:

  1. Migrate PerformDowngradeTask to Coroutines #11651
  2. migrated AnkiStatsTaskHandler.createReviewSummaryStatistics() to suspend function #11667
  3. migrated LoadPronunciationActivity to Coroutines #11681
  4. migrated CollectionLoader to Coroutines #11816
  5. Migrated CollectionTask.AddNote to Coroutines #11952
  6. Migrated CollectionTask.UpdateNote to Coroutines #12199
  7. Migrated CollectionTask.UpdateMultipleNotes to Coroutines #12272
  8. Migrated LoadDeck to Coroutines #12328
  9. Coroutines migration PreloadNextCard #12362
  10. Coroutines migration CollectionTask.DeleteModel #12365
  11. Migrated LoadCollectionComplete to Coroutines #12361
  12. Coroutines migration CollectionTask.SaveCollection #12330
  13. migrated AnkiStatsTaskHandler.createStatisticsOverview() to suspend function #11628
  14. migrated AnkiStatsTaskHandler.createChart() to suspend function #11556
  15. Coroutines migration DeleteMedia #12373
  16. Coroutines migration CheckMedia #12375
  17. Coroutines migration CollectionTask.DeleteDeck #12391
  18. Coroutines migration ChangeSortField #12421
  19. Coroutines migration add field #12434
  20. Migrated CollectionTask. ConfReset to Kotlin Coroutines #12454
  21. Migrated CollectionTask.Flag to Coroutines #12462
  22. Migrated RepairCollection to Coroutines #12498
  23. Coroutines migration UpdateValuesFromDeck #12522
  24. Coroutines migration CollectionTask.MarkNoteMulti #12525
  25. Coroutines migration conf change #12534
  26. Coroutines migration save model #12535
  27. Migrated CountModels to Coroutines #12541
  28. Migrated ConfRemove to Coroutines #12546
  29. Migrated EmptyCram to Coroutines #12551
  30. Migrated CheckCardSelection to Coroutines #12556
  31. Migrated CollectionTask.Reset to Coroutines #12557
  32. Coroutines migration RenderBrowserQA #12571
  33. Coroutines migration DeleteNoteMulti #12577
  34. Coroutines migration RebuildCram #12584
  35. Coroutines migration SuspendCardMulti #12585
  36. Migrated CollectionTask.Reorder to Coroutines #12591
  37. Coroutines migration ConfSetSubdecks #12592

After the migration, I realized that I have completely deviated from my initial plans but for good. Migrating with the newer approach made the codes much cleaner and easy to follow.

Final Results

Since my changes do not include UI changes, I don’t have anything visual to show but my work is clearly visible through my pull requests. Although I couldn’t complete everything within the given timeline, I can say that most of the migration has been done, and the remaining will be done in the continuation. I’ll also keep contributing to the AnkiDroid after GSoC and will put my efforts to improve the codebase. I would like to thank Shridhar, Arthur, Mike, Damien, Luksbit, David, and all the other folks around the community. You guys are awesome and I’ve had a very good time together with you spending my summer discussing and programming.

Learning Outcomes

Before working on GSoC I did not have much experience with Git-GitHub workflow, PRs, Code reviews, coding discussion, planning, having conversations with community members, etc. These are the most valuable things I would say I learned from my GSoC period. Also working on the project I learned Kotlin Coroutines in great depth along with the concepts of AsyncTask, and how Android used to be before Kotlin. I would say GSoC has had a very huge impact on my skills and my experience was awesome.

--

--

divyanshdxn

I am a passionate android developer. I write posts on latest tech, and mainly about android stuffs.