junit test in android from scratch

Android DataBase Test Case

https://commonsware.com/AndExplore/pages/chap-t26-002

Api testing

https://wiremock.org/about/

JUnit Test

https://medium.com/@fabioCollini/android-testing-using-dagger-2-mockito-and-a-custom-junit-rule-c8487ed01b56

https://www.nerd.vision/post/jacoco-coverage-of-util-classes

https://proandroiddev.com/unit-tests-with-dagger2-retrofit2-rxjava2-and-mockk-android-1c268fa77957

https://www.raywenderlich.com/195-android-unit-testing-with-mockito#toc-anchor-001

https://www.raywenderlich.com/books/android-test-driven-development-by-tutorials/v2.0/chapters/5-unit-tests#toc-chapter-010-anchor-002

https://www.raywenderlich.com/books/android-test-driven-development-by-tutorials/v2.0/chapters/6-architecting-for-testing#toc-chapter-011-anchor-002

https://mockk.io/ANDROID.html

Android & Kotlin Tutorials

Android Unit Testing with Mockito

In this Unit Testing with Mockito tutorial for Android, you will learn how to refactor an app in a way that makes it easy to write unit tests in Kotlin using Mockito. By Fernando Sproviero J

Version

  • Kotlin 1.2, Android 4.4, Android Studio 3

The need for writing tests in software development is often underestimated and relegated to later stages of a project. Sometimes not writing any tests is considered right for mobile apps.

You may have heard several excuses, a few of which are:

  • “Mobile apps are frontend apps, the real logic is in the backend, so backend apps should be tested instead.”
  • “Mobile apps are difficult to unit test, because most of the logic is done in the UI. At most, you should only care about UI tests.”
  • “Mobile apps are “simple” or “tiny” compared to backend apps. Thus, effort should be put in the features instead of wasting time making tests.”

Mobile apps are actually becoming larger and more complex. Hence, teams are also growing in size.

Some companies even have separate teams that focus on specific features. And often, there’s another team that has to:

  • Merge all the features.
  • Upload the final build to Playstore/AppStore.

This increase in code complexity and team collaboration may jeopardize the proper functioning of your application.

Writing good tests can cover this!

In this tutorial, you’ll be refactoring a starter project to use the Model-View-Presenter presentation architecture pattern and write unit tests using Mockito.

But first of all, let’s take a look at the testing pyramid.

Testing pyramid

Tests are typically broken into three different kinds:

testing pyramid

The Testing Pyramid, showing the three categories of tests that you should include in your app’s test suite

  • UI Tests:
    These tests interact with the UI of your app, they emulate the user behavior and assert UI results. These are the slowest and most expensive tests you can write because they require a device/emulator to run. On Android, the most commonly used tools for UI testing are Espresso and UI Automator.
  • Integration Tests:
    When you need to check how your code interacts with other parts of the Android framework but without the complexity of the UI. These tests don’t require a device/emulator to run. On Android, the most common tool for integration testing is Roboelectric.
  • Unit Tests:
    The system under test (SUT) is one class and you focus only on it. All dependencies are considered to be working correctly (and ideally have their own unit tests :]), so they are mocked or stubbed.
    These tests are the fastest and least expensive tests you can write because they don’t require a device/emulator to run. On Android, the most commonly used tools for unit testing are JUnit and Mockito.

A typical rule of thumb is to have the following split among the categories:

  • UI Tests: 10%
  • Integration Tests: 20%
  • Unit Tests: 70%

Because unit tests are so important in the testing pyramid and also easy to write, this tutorial will focus on them.

Note: This tutorial assumes you have previous experience with developing for Android in Kotlin. If you are unfamiliar with the language have a look at this tutorial. If you’re beginning with Android, check out some of our Getting Started and other Android tutorials.

Getting started

Download the starter project. Extract the zip file but don’t open the project in Android Studio yet.

You’ll be working with this simple app named “IngrediSearch” that allows users to search for recipes and favorite them.Note: For this app to work, please ensure the following:

  • Get your Food2Fork API key
  • Create a keystore.properties file with the following content (including the quotes):
    FOOD2FORK_API_KEY="YOUR API KEY"
  • Place this file in the root project.

With the keystore.properties file added, open the project in Android Studio 3.0.1 or greater.

Build and run the project to become familiar with the application features.

app welcome pageapp search page
app results pageapp recipe detail page

The project contains the following main files:

  • MainActivity.kt: Contains the main screen.
  • SearchActivity.kt: Allows the user to input ingredients.
  • SearchResultsActivity.kt: Searches for recipes using the API and shows the results. It also provides the ability to add or remove favorites.
  • RecipeActivity.kt: Shows the recipe detail.
  • FavoritesActivity.kt: Shows the list of favorites.
  • RecipeRepository.kt: Interacts with the API to search for recipes. It also stores the favorites in SharedPreferences.
  • RecipeAdapter.kt: Adapter used to show the list in SearchResultsActivity and FavoritesActivity.

Before you start unit testing, it’s best to ask one very important question…

Is this unit testable?

By checking the source code you will find:

Logic in the Activities

class SearchActivity : ChildActivity() {

  override fun onCreate(savedInstanceState: Bundle?) {
    ...
    searchButton.setOnClickListener {
      // 1
      val query = ingredients.text.toString().trim()
      // 2
      if (query.isBlank()) {
        // 3
        Snackbar.make(searchButton, getString(R.string.search_query_required), Snackbar
            .LENGTH_LONG).show()
      } else {
        // 4
        startActivity(searchResultsIntent(query))
      }
    }
  }
}

When the user clicks the search button:

  1. Trim the ingredients text string entered by the user.
  2. Check if it’s blank.
  3. When it’s blank, then show an error message.
  4. If it’s not blank, then proceed to the next screen.

Activity doing everything

class SearchResultsActivity : ChildActivity() {

  private fun search(query: String) {
    // 1
    showLoadingView()
    // 2
    repository.getRecipes(query, object : RecipeRepository.RepositoryCallback<List<Recipe>> {
      override fun onSuccess(recipes: List<Recipe>?) {
        if (recipes != null && recipes.isNotEmpty()) {
          // 3
          showRecipes(recipes)
        } else {
          // 4
          showEmptyRecipes()
        }
      }

      override fun onError() {
        // 5
        showErrorView()
      }
    })
  }

To perform a search:

  1. Because the operation is asynchronous, the activity must show a loading view.
  2. Call the repository of recipes.
  3. If there are recipes, show them!
  4. When no recipes are found, a “No recipes were found” message is shown.
  5. Show an error view if there was an error fetching the recipes.

Adapter doing too much logic

Inside this same activity, you’ll find:

    list.adapter = RecipeAdapter(recipes, object : RecipeAdapter.Listener {
      override fun onAddFavorite(item: Recipe) {
        // 1
        item.isFavorited = true
        // 2
        repository.addFavorite(item)
        // 3
        list.adapter.notifyItemChanged(recipes.indexOf(item))
      }
      ...
    })
  1. Altering the model (favorited status).
  2. Calling the repository.
  3. Updating the view to show the altered model.

Conclusion

Because these are so embedded into the Android activities/adapter, they are not efficiently unit testable. A refactor must be done!

Model-View-Presenter

You’ll refactor the project to the Model-View-Presenter structure. This will ease the creation of unit tests.Note: If you already know about MVP you can skip to the next section where the project is already refactored to MVP and ready to write unit tests.

model view presenter


Also called just MVP

  • Model:
    All your data classes, API connectors, databases.
  • View:
    Activities, Fragments and any Android Views. It’s responsible for showing the data and propagating the user’s UI actions to the corresponding presenter methods.
  • Presenter:
    Knows about the model and the view. Publishes methods that will be called by the view. These methods usually involve fetching data, manipulating it, and deciding what to show in the view.

Refactoring to MVP

Creating your first Presenter

First, you’ll refactor the SearchActivity to MVP.

Therefore, create a new class by right-clicking on the com.raywenderlich.ingredisearch package and choosing New-Kotlin File/Class. Name the class SearchPresenter and add the following:

class SearchPresenter {
  // 1
  private var view: View? = null

  // 2
  fun attachView(view: View) {
    this.view = view
  }

  // 3
  fun detachView() {
    this.view = null
  }

  // 4
  fun search(query: String) {
    // 5
    if (query.trim().isBlank()) {
      view?.showQueryRequiredMessage()
    } else {
      view?.showSearchResults(query)
    }
  }

  // 6
  interface View {
    fun showQueryRequiredMessage()
    fun showSearchResults(query: String)
  }
}
  1. The presenter knows about the view, so it has to hold a reference to it.
  2. When the view is created, it must attach to the presenter.
  3. You must detach from the presenter when the view is destroyed.
  4. This presenter exposes the search method.
  5. If the query is blank then the view has to show a “query required” message. If it’s not blank, it’ll show the results.
  6. A View interface that your activity will have to conform to.

Implementing your first View

Now, open SearchActivity and modify it to the following:

// 1
class SearchActivity : ChildActivity(), SearchPresenter.View {

  private val presenter: SearchPresenter = SearchPresenter()

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_search)

    // 2
    presenter.attachView(this)

    searchButton.setOnClickListener {
      val query = ingredients.text.toString()
      // 3
      presenter.search(query)
    }
  }

  override fun onDestroy() {
    // 4
    presenter.detachView()
    super.onDestroy()
  }

  // 5
  override fun showQueryRequiredMessage() {
    // Hide keyboard
    val view = this.currentFocus
    if (view != null) {
      val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
      imm.hideSoftInputFromWindow(view.windowToken, 0)
    }

    Snackbar.make(searchButton, getString(R.string.search_query_required), Snackbar
        .LENGTH_LONG).show()
  }

  // 6
  override fun showSearchResults(query: String) {
    startActivity(searchResultsIntent(query))
  }
}
  1. Conform to the SearchPresenter.View interface by implementing 5 and 6.
  2. Create a new instance of the presenter and attach the view.
  3. Whenever the user clicks the search button, instead of the activity doing any logic, just call the search method of the presenter.
  4. When the view is destroyed you must tell the presenter to detach the view.
  5. Implement showQueryRequiredMessage required by the SearchPresenter.View interface.
  6. SearchPresenter.View also requires you to implement showSearchResults.

Creating the SearchResults presenter

Create a SearchResultsPresenter class.

// 1
class SearchResultsPresenter(val repository: RecipeRepository) {
  private var view: SearchResultsPresenter.View? = null
  private var recipes: List<Recipe>? = null

  // 2
  fun attachView(view: SearchResultsPresenter.View) {
    this.view = view
  }

  fun detachView() {
    this.view = null
  }

  // 3
  interface View {
    fun showLoading()
    fun showRecipes(recipes: List<Recipe>)
    fun showEmptyRecipes()
    fun showError()
    fun refreshFavoriteStatus(recipeIndex: Int)
  }
}
  1. This presenter will make the API request therefore it has RecipeRepository as dependency.
  2. You also need to attach/detach.
  3. A View interface that your activity will have to conform to.

You may have noticed that you’re repeating the attach/detach logic here, so let’s create a BasePresenter:

abstract class BasePresenter<V> {
  protected var view: V? = null

  fun attachView(view: V) {
    this.view = view
  }

  fun detachView() {
    this.view = null
  }
}

Now extend from this class, remove the view property and the attach/detach methods:

class SearchResultsPresenter(private val repository: RecipeRepository) : 
    BasePresenter<SearchResultsPresenter.View>() {
  private var recipes: List<Recipe>? = null

  interface View {
    fun showLoading()
    fun showRecipes(recipes: List<Recipe>)
    fun showEmptyRecipes()
    fun showError()
    fun refreshFavoriteStatus(recipeIndex: Int)
  }
}

Add the following method:

  // 1
  fun search(query: String) {
    view?.showLoading()
    // 2
    repository.getRecipes(query, object : RecipeRepository.RepositoryCallback<List<Recipe>> {
      // 3
      override fun onSuccess(recipes: List<Recipe>?) {
        this@SearchResultsPresenter.recipes = recipes
        if (recipes != null && recipes.isNotEmpty()) {
          view?.showRecipes(recipes)
        } else {
          view?.showEmptyRecipes()
        }
      }

      // 4
      override fun onError() {
        view?.showError()
      }
    })
  }
  1. This presenter exposes the search method.
  2. Call the repository to get recipes asynchronously.
  3. If the call is successful show the recipes (or empty if there are none).
  4. Whenever there is an error with the call, show the error.

Add the following extra methods:

  // 1
  fun addFavorite(recipe: Recipe) {
    // 2
    recipe.isFavorited = true
    // 3
    repository.addFavorite(recipe)
    // 4
    val recipeIndex = recipes?.indexOf(recipe)
    if (recipeIndex != null) {
      view?.refreshFavoriteStatus(recipeIndex)
    }
  }

  // 5
  fun removeFavorite(recipe: Recipe) {
    repository.removeFavorite(recipe)
    recipe.isFavorited = false
    val recipeIndex = recipes?.indexOf(recipe)
    if (recipeIndex != null) {
      view?.refreshFavoriteStatus(recipeIndex)
    }
  }
  1. Expose the addFavorite method.
  2. Alter the state of the model.
  3. Call the repository to save the favorite.
  4. Tell the view to refresh with the favorited status.
  5. Analogously, expose the removeFavorite method.

Implementing SearchResultsPresenter.View

Now, open SearchResultsActivity and modify it to the following:

// 1
class SearchResultsActivity : ChildActivity(), SearchResultsPresenter.View {

  private val presenter: SearchResultsPresenter by lazy {SearchResultsPresenter(RecipeRepository.getRepository(this))}

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_list)

    val query = intent.getStringExtra(EXTRA_QUERY)
    supportActionBar?.subtitle = query

    // 2
    presenter.attachView(this)
    // 3
    presenter.search(query)
    retry.setOnClickListener { presenter.search(query) }
  }
}
  1. Conform to the SearchResultsPresenter.View interface.
  2. Instantiate the presenter with the repository and attach the view.
  3. Whenever the user enters this screen, instead of the activity doing any logic, just call the search method of the presenter.
  4. When the view is destroyed you must tell the presenter to detach the view.

Implement the SearchResultsPresenter.View interface:

  override fun showEmptyRecipes() {
    loadingContainer.visibility = View.GONE
    errorContainer.visibility = View.GONE
    list.visibility = View.VISIBLE
    noresultsContainer.visibility = View.VISIBLE
  }

  override fun showRecipes(recipes: List<Recipe>) {
    loadingContainer.visibility = View.GONE
    errorContainer.visibility = View.GONE
    list.visibility = View.VISIBLE
    noresultsContainer.visibility = View.GONE

    setupRecipeList(recipes)
  }

  override fun showLoading() {
    loadingContainer.visibility = View.VISIBLE
    errorContainer.visibility = View.GONE
    list.visibility = View.GONE
    noresultsContainer.visibility = View.GONE
  }

  override fun showError() {
    loadingContainer.visibility = View.GONE
    errorContainer.visibility = View.VISIBLE
    list.visibility = View.GONE
    noresultsContainer.visibility = View.GONE
  }

  override fun refreshFavoriteStatus(recipeIndex: Int) {
    list.adapter.notifyItemChanged(recipeIndex)
  }

Implement the missing method:

  private fun setupRecipeList(recipes: List<Recipe>) {
    list.layoutManager = LinearLayoutManager(this)
    list.adapter = RecipeAdapter(recipes, object : RecipeAdapter.Listener {
      override fun onClickItem(recipe: Recipe) {
        startActivity(recipeIntent(recipe.sourceUrl))
      }

      override fun onAddFavorite(recipe: Recipe) {
        // 1
        presenter.addFavorite(recipe)
      }

      override fun onRemoveFavorite(recipe: Recipe) {
        // 2
        presenter.removeFavorite(recipe)
      }
    })
  }
  1. When adding a favorite, now the adapter listener just calls the presenter’s addFavorite method.
  2. Also, when the user wants to remove a favorite, just call the presenter’s removeFavorite method.

MVP Refactor done!

Now that the refactor was done, you’ll be able to create unit tests.

Build and run the app and make sure the app behaves just as it did before the refactor.

You can also download the MVP refactored project if you want to. Remember to add the keystore.properties file in order to open the project.

Using Mockito

Setup Mockito dependencies

Open the application’s build.gradle file and add the following dependency:

dependencies {
  ...
  testImplementation 'com.nhaarman:mockito-kotlin-kt1.1:1.5.0'
  ...
}

Mockito-Kotlin is a wrapper library around Mockito.

It provides top-level functions to allow for a more idiomatic approach and also solves a few issues with using the Mockito java library in Kotlin. Check its wiki for more information.

State & Behavior verification

In state verification, you first have the system under test (SUT) configured with all the necessary dependencies (setup phase). Secondly, you perform a certain operation (exercise phase). Finally, you examine the state of the object and verify it’s the expected one (verification phase). This is sometimes called black-box testing. Usually, JUnit is used for this.

In behavior verification, instead, you specify which methods are to be invoked on the dependencies, in other words, you setup expectations, thus verifying not that the ending state is correct, but that the methods were invoked correctly. This is sometimes called white-box testing. Usually, Mockito is used for this.

Mockito main features

  • Mock:
    The SUT usually has dependencies that are necessary for the SUT to work. If you want to verify a method was called by the SUT, you mock the dependency class and then verify the mocked dependency method was called.
  • Stubbing:
    Sometimes your SUT will follow a certain path or another depending on the results of methods called on its dependencies. To force a dependency to always respond the same way, you need to stub the method.

At last, it’s time for some unit testing! :]

Search unit tests

You’ll create a unit test that verifies that the presenter calls the view’s showQueryRequiredMessage when an empty search is performed.

First delete the ExampleUnitTest:
Delete ExampleUnitTest

Add a new class called SearchTests, with the following content:

package com.raywenderlich.ingredisearch

import com.nhaarman.mockito_kotlin.mock
import com.nhaarman.mockito_kotlin.verify
import org.junit.Test

class SearchTests {
  // 1
  @Test
  fun search_withEmptyQuery_callsShowQueryRequiredMessage() {
    // 2
    val presenter = SearchPresenter()
    // 3
    val view: SearchPresenter.View = mock()
    presenter.attachView(view)

    // 4
    presenter.search("")

    // 5
    verify(view).showQueryRequiredMessage()
  }
}
  1. Every unit test must start with the @Test annotation.
  2. Instantiate the presenter.
  3. Because you don’t need a real view that conforms to the interface, you can mock it.
    Then attach this view to the presenter.
  4. Call the search method with an empty query.
  5. Verify on the mocked view that the presenter calls showQueryRequiredMessage

Now to run the test, press on the little green arrow (the arrow will have a circle after the first run of the tests) to the left of the class declaration:

Run SearchTests

Hopefully you’ll get all green! :]

Successful test results

Refactoring the unit test

Because all SearchTests will basically share the same setup, you should add a setup() function with a @Before annotation as follows:

class SearchTests {

  private lateinit var presenter : SearchPresenter
  private lateinit var view : SearchPresenter.View

  @Before
  fun setup() {
    presenter = SearchPresenter()
    view = mock()
    presenter.attachView(view)
  }
  ...

The function marked @Before is executed before any test, therefore it’s a good place to setup objects/mocks. It’s also common to see a tearDown() function marked @After in test classes, which is run when a test completes.

Modify your first test with the following:

  @Test
  fun search_withEmptyQuery_callsShowQueryRequiredMessage() {
    presenter.search("")

    verify(view).showQueryRequiredMessage()
  }

Verify a method is never called

You can also test that a function is never called by adding the following test:

  @Test
  fun search_withEmptyQuery_doesNotCallsShowSearchResults() {
    presenter.search("")

    verify(view, never()).showSearchResults(anyString())
  }

Note: Android Studio will mark never() as an unresolved reference. Make sure you import the com.nhaarman.mockito_kotlin option which is the Mockito wrapper.

Search results tests

Kotlin default final classes/methods

Before proceeding to create these tests, it’s important to mention that Kotlin classes and methods by default are final. Mockito won’t work with final classes/methods, but there are a few workarounds:

  • Add the open keyword to classes and methods that you’ll mock.
  • Create an interface and have the class implement the interface. Then, just mock the interface (interfaces are open by default).
  • Use mock-maker-inline. You’ll do this later.

Repository refactor

Because in the following tests you’ll mock the repository, we’re going to take the interface approach.

So, use Shift+F6 to rename the RecipeRepository class to RecipeRepositoryImpl and create a new RecipeRepository interface with all the public methods, you can also move the RepositoryCallback outside:

interface RecipeRepository {
  fun addFavorite(item: Recipe)
  fun removeFavorite(item: Recipe)
  fun getFavoriteRecipes(): List<Recipe>
  fun getRecipes(query: String, callback: RepositoryCallback<List<Recipe>>)
}

interface RepositoryCallback<in T> {
  fun onSuccess(t: T?)
  fun onError()
}

Open RecipeRepositoryImpl and implement RecipeRepository:

class RecipeRepositoryImpl(private val sharedPreferences: SharedPreferences) :
    RecipeRepository

Add the override keyword to the corresponding methods (also, be sure to remove RepositoryCallback from RecipeRepositoryImpl if you added it into the interface file).

Also, open SearchResultsPresenter and modify it to use the interface:

class SearchResultsPresenter(val repository: RecipeRepository) :
    BasePresenter<SearchResultsPresenter.View>()

And fix the anonymous RepositoryCallback:

repository.getRecipes(query, object : RepositoryCallback<List<Recipe>> {

Setup Search results tests

Add a new class called SearchResultsTests to the test package:

package com.raywenderlich.ingredisearch

import com.nhaarman.mockito_kotlin.mock
import org.junit.Before

class SearchResultsTests {

  private lateinit var repository: RecipeRepository
  private lateinit var presenter: SearchResultsPresenter
  private lateinit var view: SearchResultsPresenter.View

  @Before
  fun setup() {
    repository = mock()
    view = mock()
    presenter = SearchResultsPresenter(repository)
    presenter.attachView(view)
  }
}

Add the following tests:

  // 1
  @Test
  fun search_callsShowLoading() {
    presenter.search("eggs")

    verify(view).showLoading()
  }

  // 2
  @Test
  fun search_callsGetRecipes() {
    presenter.search("eggs")

    verify(repository).getRecipes(eq("eggs"), any())
  }

These tests verify:

  1. That the view is shown as “loading” whenever the presenter is required to search.
  2. If the repository is called with the corresponding parameters (“eggs”), then the eq matcher is used to verify that it’s called with the same string. The any matcher was used for the callback parameter because you don’t care about it.

Try and run these search results tests using the green arrow next to the test class name.

Stub a callback

Now, create a test that stubs the response of the recipes repository and verifies that the presenter calls showRecipes on the mocked view.

  @Test
  fun search_withRepositoryHavingRecipes_callsShowRecipes() {
    // 1
    val recipe = Recipe("id", "title", "imageUrl", "sourceUrl", false)
    val recipes = listOf<Recipe>(recipe)

    // 2
    doAnswer {
      val callback: RepositoryCallback<List<Recipe>> = it.getArgument(1)
      callback.onSuccess(recipes)
    }.whenever(repository).getRecipes(eq("eggs"), any())

    // 3
    presenter.search("eggs")

    // 4
    verify(view).showRecipes(eq(recipes))
  }
  1. Create a list of recipes.
  2. Stub the repository getRecipes method to return these recipes.
  3. Call the search method.
  4. Verify that the presenter calls showRecipes on the mocked view with the list of recipes.

Go ahead and run the new test to make sure all is good.

Verify state

The following test is just a JUnit test:

  @Test
  fun addFavorite_shouldUpdateRecipeStatus() {
    // 1
    val recipe = Recipe("id", "title", "imageUrl", "sourceUrl", false)

    // 2
    presenter.addFavorite(recipe)

    // 3
    Assert.assertTrue(recipe.isFavorited)
  }
  1. Create a recipe.
  2. Call the addFavorite method.
  3. Verify that the recipe isFavorited flag has changed.

Run the test to make sure the state of a recipe is changed correctly when marked as a favorite.

RecipeRepository tests

Before creating the tests, open RecipeRepositoryImpl and look at the following functions:

  override fun addFavorite(item: Recipe) {
    // 1
    val favorites = getFavoriteRecipes() + item
    saveFavorites(favorites)
  }

  // 2
  private fun saveFavorites(favorites: List<Recipe>) {
    val editor = sharedPreferences.edit()
    editor.putString(FAVORITES_KEY, gson.toJson(favorites))
    editor.apply()
  }
  1. The addFavorite method, first calls getFavoriteRecipes and appends an item.
  2. Then it saves to SharedPreferences using a JSON format.

You’ll create a test that verifies this behavior.

Because you’ll need to stub getFavoriteRecipes() and also you’ll need to call the real addFavorite method, a mock on the RecipeRepository interface won’t work. You need to spy on a real instance of RecipeRepositoryImpl. More on the spy feature later.

Mock maker inline

Now, recall that Kotlin by default has final classes and final methods (unless you use the open keyword).
So, instead of adding the open keyword to the RecipeRepositoryImpl class and methods, create a text file under app/src/test/resources/mockito-extensions called org.mockito.plugins.MockMaker with the following content (it may be easier to switch to the Project view in the Project pane in order to add the new directory and text file):

mock-maker-inline
mockito-extensions file

This will enable you to mock/spy on real classes without adding the open keyword.

Spy the repository implementation

Add a new class to the test package called RepositoryTests with the following content:

package com.raywenderlich.ingredisearch

import android.content.SharedPreferences
import com.nhaarman.mockito_kotlin.mock
import com.nhaarman.mockito_kotlin.spy
import com.nhaarman.mockito_kotlin.whenever
import org.junit.Before

class RepositoryTests {
  private lateinit var spyRepository: RecipeRepository
  private lateinit var sharedPreferences: SharedPreferences
  private lateinit var sharedPreferencesEditor: SharedPreferences.Editor

  @Before
  fun setup() {
    // 1
    sharedPreferences = mock()
    sharedPreferencesEditor = mock()
    whenever(sharedPreferences.edit()).thenReturn(sharedPreferencesEditor)

    // 2
    spyRepository = spy(RecipeRepositoryImpl(sharedPreferences))
  }
}
  1. You need to mock SharedPreferences and the corresponding editor.
  2. Because you’ll stub the RecipeRepository‘s getRecipes method but you also need to call the real addFavorite method on the same object, instead of a mock you need a spy.

Finally, create the test:

  @Test
  fun addFavorite_withEmptyRecipes_savesJsonRecipe() {
    // 1
    doReturn(emptyList<Recipe>()).whenever(spyRepository).getFavoriteRecipes()

    // 2
    val recipe = Recipe("id", "title", "imageUrl", "sourceUrl", false)
    spyRepository.addFavorite(recipe)

    // 3
    inOrder(sharedPreferencesEditor) {
      // 4
      val jsonString = Gson().toJson(listOf(recipe))
      verify(sharedPreferencesEditor).putString(any(), eq(jsonString))
      verify(sharedPreferencesEditor).apply()
    }
  }
  1. Stub the getFavoriteRecipes() with an empty list. Notice that when stubbing spies you need to use doReturn/whenever/method.
  2. Call the real addFavorite method with a recipe.
  3. Check that the subsequent verifications are executed in the exact order.
  4. Verify that the list is saved correctly with JSON format.

Go ahead and run the repository tests to see the spy in action!

Where To Go From Here?

Congratulations! You’ve just learned the basics of using Mockito for unit testing.

You can download the final project here. Remember to add the keystore.properties file in order to open the project.

In this tutorial, you added the unit tests after writing the code. In Test Driven Development (TDD), you write the unit tests first and only add code to pass the currently failing unit test.

I suggest reading the following:

  • Mockito reference: To delve more into this topic, please have a look at the Mockito-Kotlin and Mockito wikis.
  • Mocks aren’t stubs: You’ll commonly hear in the jargon “You should mock that”, but they aren’t always strictly referring to mocks. An article from Martin Fowler explains the difference.
  • Dependency injection: In order to make your app more testable, it’s good to have your dependencies injected somehow. This Dagger 2 tutorial will help you with that.
  • Test patterns: Because writing tests is a bit of an art form, this book from Gerard Meszaros will explain some great patterns to you. It’s an incredible reference.
  • Espresso codelab: If you’re wondering how UI tests are done, this codelab from Google Developers will help you get started.

For even more testing practice, check out our book, Android Test-Driven Development by Tutorials.

By navalkishorjha

Git config

https://developer.lsst.io/v/DM-5063/tools/git_setup.html

[user]
;user details change the email
name = Naval Kishor Jha
email = er.navalkishor@yahoo.in
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
autocrlf = true
# VSCode
#editor = code --wait
# Don't consider trailing space change as a cause for merge conflicts
whitespace = -trailing-space
[color]
# Enable colors in color-supporting terminals
ui = auto
[grep]
break = true
heading = true
lineNumber = true
# Consider most regexes to be ERE
extendedRegexp = true
[alias]
# List available aliases
aliases = !git config --get-regexp alias | sed -re 's/alias\.(\S)\s(.)$/\1 = \2/g'
# Command shortcuts
ci = commit
co = checkout
st = status
# Display tree-like log, because default log is a pain…
lg = log --date=relative --pretty=tformat:'%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%an %ad)%Creset'
# Useful when you have to update your last commit
# with staged files without editing the commit message.
oops = commit --amend --no-edit
# Ensure that force-pushing won't lose someone else's work (only mine).
push-with-lease = push --force-with-lease
# Rebase won’t trigger hooks on each "replayed" commit.
# This is an ugly hack that will replay each commit during rebase with the
# standard commit command which will trigger hooks.
rebase-with-hooks = rebase -x 'git reset --soft HEAD~1 && git commit -C HEAD@{1}'
# List local commits that were not pushed to remote repository
review-local = "!git lg @{push}.."
# Edit last commit message
reword = commit --amend
# Undo last commit but keep changed files in stage
uncommit = reset --soft HEAD~1
#sets things up the way they were before the commit
undo = reset --soft HEAD^
stash-all = stash save --include-untracked
glog = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset'
# Remove file(s) from Git but not from disk
untrack = rm --cache --
tags = "tag -l"
branches = "branch -a"
remotes = "remote -v"
# Create a commit that will be automatically squashed as a fixup when you
# run git rebase --autosquash
fixup = "commit --fixup=HEAD"
# Better diffs for prose
wdiff = "diff --color-words"
alias = ! git config --get-regexp ^alias\\. | sed -e s/^alias\\.// -e s/\\ /\\ =\\ /
p = push
ll = 'log --oneline'
glist = config --global alias.gl 'config --global -l'
se = !git rev-list --all | xargs git grep -F
By navalkishorjha

Linux and mac useful tips

Bash Startup Files

When invoked as an interactive login shell, Bash looks for the /etc/profile file, and if the file exists , it runs the commands listed in the file. Then Bash searches for ~/.bash_profile~/.bash_login, and ~/.profile files, in the listed order, and executes commands from the first readable file found.

When Bash is invoked as an interactive non-login shell, it reads and executes commands from ~/.bashrc, if that file exists, and it is readable.

Difference Between .bashrc and .bash_profile

.bash_profile is read and executed when Bash is invoked as an interactive login shell, while .bashrc is executed for an interactive non-login shell.

Use .bash_profile to run commands that should run only once, such as customizing the $PATH environment variable .

Put the commands that should run every time you launch a new shell in the .bashrc file. This include your aliases and functions , custom prompts, history customizations , and so on.

Create .bash_profile

To create the bash_profile, proceed with the following steps:

  1. Open the terminal.
  2. Move the home directory using the following command:
    cd ~/
  3. Use the touch command to create the bash_profile as follows:
    touch .bash_profile

Edit .bash_profile

using your favourite editor and put this :

#change the bold keyword as per your system

ANDROID_SDK=/Users/username/Library/Android/sdk
PlatformTool_PATH=”$ANDROID_SDK/platform-tools”
BuildTools=”$ANDROID_SDK/build-tools/30.0.2/”
export PATH=”$PATH:$ANDROID_SDK:$PlatformTool_PATH:$BuildTools”
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi

Create .bashrc

Use same step as in .bash_profile

Edit .bashrc

using your favourite editor and put this :

#Linux


alias ll=’ls -alFh’
alias l=’ls -CFah’
alias lt=’du -sh * | sort -h’
alias CD=”cd ~/Desktop”
alias Cd=”cd ~/Documents”
alias Cdo=”cd ~/Downloads”
alias Cdop=”cd ~/Downloads && open .”
alias Cdp=”cd ~/Documents && open .”
alias CDp=”cd ~/Desktop && open .”

#git

alias gh=’history|grep’
alias gs=’git status’
alias gl=’git log –oneline’
alias gf=’git fetch’
alias gm=’cd git rev-parse --show-toplevel && git checkout master && git pull’
alias cg=’cd git rev-parse --show-toplevel

#android

ANDROID_SDK=/Users/kinaval/Library/Android/sdk
PlatformTool_PATH=”$ANDROID_SDK/platform-tools”
BuildTools=”$ANDROID_SDK/build-tools/30.0.2/”
export PATH=”$PATH:$ANDROID_SDK:$PlatformTool_PATH:$BuildTools”

alias alog=’adb logcat | tee ‘
alias alogc=’adb logcat > log.txt’
alias count=’find . -type f | wc -l’
alias cpv=’rsync -ah –info=progress2′

#paython

alias ve=’python3 -m venv ./venv’
alias va=’source ./venv/bin/activate’

Now save all file it and open terminal for this time use

source ~/.bash_profile

By navalkishorjha

Android Studio plugin to easy work

  1. SonarLint
  2. JSON Editor
  3. Rainbow Brackets
  4. SQLDelight
  5. ADB Idea
  6. JSON To Kotlin Class
  7. code-iris
  8. Codota
  9. String Manipulation
  10. Easy Gradle
  11. Kotlin Fill Class
  12. Key Promoter X
  13. Clear Cache Plugin
  14. FCM Push Sender
  15. JSON Helper —
  16. Json String into Kotlin data class
  17. Python Community Edition
  18. Rainbow CSV
  19. Database development, scripting and navigation tool
  20. SQLAndroid
  21. Android ButterKnife Zelezny injections
  22. SQLScout
  23. CodeGlance
  24. Indent Rainbow
  25. TabNine
  26. Kite AI
  27. Material Theme UI

https://betterprogramming.pub/the-top-20-android-studio-plugins-4331f5cdeb80

https://www.dunebook.com/best-android-studio-plugins/

video compresser online free

https://compress-video-online.com/

https://github.com/Genymobile/scrcpy/blob/master/doc/windows.md: Android Studio plugin to easy work

https://github.com/mik3y/usb-serial-for-android

By navalkishorjha

Room Database pre-populated data! and Database Upgrade

@Query("UPDATE tableName SET 
    field1 = :value1,
    field2 = :value2, 
    ...
    //some more fields to update
    ...
    field_N= :value_N
    WHERE id = :id)

int updateTour(long id, 
               Type value1, 
               Type value2, 
               ... ,
               // some more values here
               ... ,
               Type value_N);

Example:

Entity:

@Entity(tableName = "orders")
class Order {
    @NonNull
    @PrimaryKey
    @ColumnInfo(name = "order_id")
    private val id = 0

    @ColumnInfo(name = "order_title")
    private val title: String? = null

    @ColumnInfo(name = "order_amount")
    private val amount: Float? = null

    @ColumnInfo(name = "order_price")
    private val price: Float? = null

    @ColumnInfo(name = "order_desc")
    private val description: String? = null

    @ColumnInfo(name = "order_date")
    private val date: Long = 0 // ... methods, getters, setters
}

Dao:

@Dao
interface OrderDao {
    @get:Query("SELECT * FROM orders")
    val orderList: List<Any?>?

    @get:Query("SELECT * FROM orders")
    val orderLiveList: LiveData<List<Order?>?>?

    @Query("SELECT * FROM orders WHERE order_id =:orderId")
    fun getLiveOrderById(orderId: Int): LiveData<Order?>?

    /** * Updating only price * By order id  */
    @Query("UPDATE orders SET order_price=:price WHERE order_id = :id")
    fun update(price: Float?, id: Int)

    /** * Updating only amount and price * By order id  */
    @Query("UPDATE orders SET order_amount = :amount, price = :price WHERE order_id =:id")
    fun update(amount: Float?, price: Float?, id: Int)

    /** * Updating only title and description * By order id  */
    @Query("UPDATE orders SET order_desc = :description, order_title= :title WHERE order_id =:id")
    fun update(description: String?, title: String?, id: Int)

    @Update
    fun update(order: Order?)

    @Delete
    fun delete(order: Order?)

    @Query("DELETE FROM orders")
    fun deleteAll()

    @Insert(onConflict = REPLACE)
    fun insert(order: Order?)

    @Query("SELECT * FROM Order WHERE id IN (:orderIds)")
    fun loadAllByOrderId(vararg orderIds: Int): List<*>?

    @Query("SELECT * FROM Order WHERE order_title LIKE :name AND oder_date = :orderDate LIMIT 1")
    fun loadOneByNameAndReleaseYear(name: String?, orderDate: Long): Order?

    @Insert
    fun insertAll(vararg order: Order?)
}

Database:

@Database(entities = arrayOf(Order::class), version = 1, exportSchema = true)
abstract class InventoryRoomDatabase : RoomDatabase() {

   abstract fun orderDao(): OrderDao

   private class InventoryDBCallback() : RoomDatabase.Callback() {

       override fun onOpen(db: SupportSQLiteDatabase) {
           super.onOpen(db)
           INSTANCE?.let { database ->
                   var orderDao = database.orderDao()

                   // Delete all content here.
                   orderDao.deleteAll()

                   // Add sample order.
                   var order = Order().apply{ 
                       order_title="Apple";order_amount=200.00;
                       order_price=150.00;
                       order_desc="50 bugs discoount coupon";
                       order_date=1590645654
                   }
                   orderDao.insert(order)
                //add 1 more order   
                   order.order_title="talc"
                   orderDao.insert(order)

                   // TODO: Add your own order!
                   order = Order().apply{ 
                      order_title="NoteBook";order_amount=80.00;
                      order_price=80.00;
                      order_desc="0 bugs discoount on note book";
                      order_date=1590645886}
                      orderDao.insert(order)
                  }
           }
       } 
   }

   companion object {
       @Volatile
       private var INSTANCE: InventoryRoomDatabase? = null

       fun getDatabase(context: Context): WordRoomDatabase {
            // if the INSTANCE is not null, then return it,
            // if it is, then create the database
            return INSTANCE ?: synchronized(this) {
                val instance = Room.databaseBuilder(
                        context.applicationContext,
                        InventoryRoomDatabase::class.java,
                        "inventory_database"
                )
                 .addCallback(InventoryDBCallback())
                 .allowMainThreadQueries()
                 .fallbackToDestructiveMigration()
               //.addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_1_4)
                 .build()
                INSTANCE = instance
                // return instance
                instance
        }
     }
   }

val MIGRATION_1_2: Migration = object : Migration(1, 2) {
       override fun migrate(database: SupportSQLiteDatabase) {
        //simple migration 
      }
    }

val MIGRATION_2_3: Migration = object : Migration(2, 3) {
            override fun migrate(database: SupportSQLiteDatabase) {
                // sechema change migration
                database.execSQL("ALTER TABLE orders " + " ADD COLUMN last_update INTEGER")
            }
        }
val MIGRATION_3_4: Migration = object : Migration(3, 4) {
            override fun migrate(database: SupportSQLiteDatabase) {
                // Create the new table
                database.execSQL("CREATE TABLE users_new (userid TEXT, username TEXT, last_update INTEGER, PRIMARY KEY(userid))")
                // Copy the data
                database.execSQL("INSERT INTO users_new (userid, username, last_update) SELECT userid, username, last_update FROM users")
                // Remove the old table
                database.execSQL("DROP TABLE users")
                // Change the table name to the correct one
                database.execSQL("ALTER TABLE users_new RENAME TO users")
            }
        }
 
val MIGRATION_1_4: Migration = object : Migration(1, 4) {
            override fun migrate(database: SupportSQLiteDatabase) {
                // Create the new table
                database.execSQL("CREATE TABLE users_new (userid TEXT, username TEXT, last_update INTEGER, PRIMARY KEY(userid))")
                // Copy the data
                database.execSQL("INSERT INTO users_new (userid, username, last_update) SELECT userid, username, last_update FROM users")
                // Remove the old table
                database.execSQL("DROP TABLE users")
                // Change the table name to the correct one
                database.execSQL("ALTER TABLE users_new RENAME TO users")
            }
        }

for the schema to keep a record

in the module where your database file are present, default will be app

so open the build.gradle file

apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'


android {
    // ......
    defaultConfig {
     //....
        kapt {
               arguments {
                   arg("room.schemaLocation", "${projectDir}/schemas")
               }
       }
  }//defaultConfig closing

} // android



dependencies {
    def  room_version = '2.2.4'
    //....
   implementation "androidx.room:room-runtime:$room_version"
   kapt "androidx.room:room-compiler:$room_version"
     // For Kotlin use kapt instead of annotationProcessor
     // optional - Kotlin Extensions and Coroutines support for Room
   implementation "androidx.room:room-ktx:$room_version"
     //...
}

By navalkishorjha

Navodaya Class VI Entrance Exam Question Papers

Jawahar Navodaya Vidyalaya Selection Test

An Entrance examination will be conducted to select the candidates for the class VI admissions in Jawahar Navodaya Vidyalayas. The pattern and composition of the entrance exam is as under

Composition of the Test

The selection test will be of two-hour duration and will have 3 sections with only objective type questions. There are 80 questions in all for 100 marks. 15 Minutes additional time is allowed for reading the instructions.

Section Type of Test Number of Questions Marks Duration
Section – I Mental ability Test 40 50 60 Minutes
Section – II Arithmetic Test 20 25 30 Minutes
Section – III Language Test 20 25 30 Minutes
Total 80 100 2 Hours

Syllabus of the test:

Section 1: MAT- Mental Ability Test

This is a non – verbal test. Questions are based on figures and diagrams only. Questions are meant to assess general mental functioning of the candidates.

Section 2: Arithmetic Test

The main purpose of this test is to measure each candidate’s basic competencies in Arithmetic

Section 3: Language Test.
This test is to assess the reading comprehension of the candidates. The test consists of four passages. Each passage is followed by 5 questions.

For Detailed Syllabus download: JNVST Entrance Class 6 Detailed syllabus of MAT, Arithmetic Test and Language Test

For Detailed information on enrollment visit the website of Navodaya Vidyalaya Samiti

JNVST Class VI Entrance Previous Question papers

Download previous year question papers and answer keys of Jawahar Navodaya Vidyalaya STD 6 selection test from the links below

Sl No Year of JNVST Entrance Exam Question Paper Download Link
1 2019 Download
2 2018 Download
3 2017 Download 
4 2016 Download
5 2015 Download
6 2010 Download
7 2009 Download
8 2008 Download
9 2007 Download
10 2006 Download
11 2005 Download
12 2004 Download
13 2003 Download
14 2002 Download
By navalkishorjha

Kotlin: Initialization of Variable

Kotlin Code Initialization from the following place will do in given below order

class body 

init body of single in class

init body of multiple  in class then it follows the order in which it been written

constructor body of primary

constructor body of other than primary  will get called in the order it linked and invoked/called while object creation by user

Note: body means here is opening curly bracket and closing curly bracket like  { } with proper kotlin syntax

Now let’s understand by code open REPL  and write the below code and  run

you can use play ground for kotlin language click me to try

class B{
    companion object{
        fun firstInit():Int{
           println("firstInit\n")
           return 20
        }
    }
}
class A{
    var i=B.firstInit()
    val va: Int
    constructor(){
        va=10
        println("c= i:$i\n")
        i=2
        println("ci= i:$i\n")
    }
    init {
        println("i1= i:$i\n")
    }
    init {
        i=1
        println("i2= after i:$i\n")
    }
    fun see(){
        println("f= i:$i\n")
    }
    constructor(a:Int):this(){
      println("After primary= i:$i and before secondary init\n")
      i=a
      println("after secondary init c2= i:$i\n")
      //va=20
    }
}
fun main(){
    A().see()
}
main()

Output when primary constructor  A().see() is called observe the execution sequence

firstInit
i1= i:20
i2= after i:1
c= i:1
ci= i:2
f= i:2

Output, when secondary linked with primary constructor A(40).see(), is called observe the execution sequence

firstInit
i1= i:20
i2= after i:1
c= i:1
ci= i:2
After primary= i:2 and before secondary init
after secondary init c2= i:40
f= i:40

if all constructor is independent i.e not calling the other constructor from within then that constructor will get called and its output will be like primary only as per above code because the primary is not invoking any other constructor but the secondary is doing it.

Point to keep in mind while playing  with Val variable initialization in kotlin

You might have seen val  va: Int

if you have initialized val variable in the init{} body then it’s not compulsory to do in any of constructor unless you have a requirement but at only one place
class A{
val i:Int
init {
i=10
}
fun see(){
println("fi:$i")
}
constructor(){
println("ci:$i")
}
constructor(ii:Int):this(){
println("ci:$i")
}
}

A().see() 

so any val variable if you declare in class body and not initialized in init {} body then

you have to do the initialization in all of the constructors you have in class

only if not linked/invoked within class see example below else you will be in trouble

class A{
        val i:Int
        init {
           // i=10
        }
        fun see(){
          println("fi:$i")
        }
constructor(){  i=10
println("ci:$i")
}
constructor(ii:Int){  i=ii
println("ci:$i")
}
}

A().see() 

In case of linked primary constructor initializes it is fine else in all constructor

class A{
 val i:Int
init {
// i=10
}
fun see(){
println("fi:$i")
}
constructor(){  i=10
println("ci:$i")
}
constructor(ii:Int):this(){  //i=ii// not compulsory unless you have requirement as such any, as init it is done in primary constructor
println("ci:$i")
}
}

A().see() 

or you can initialize then and there in the class body like val  va: Int=10

Point to remember about the Lateinit

lateinit var lv:String

if you have initialized lateinit var variable in the init{} body then it’s not compulsory to do in any of constructor unless you have a requirement

class A{
lateinit var i:String
init {
i="10"
}
fun see(){
println("fi:$i")
}
constructor(){  //i="10"
println("ci:$i")
}
constructor(ii:String):this(){  //i=ii// not compulsory unless you have requirement as such any,as init it is done in primary constructor
println("ci:$i")
}
}

so any lateinit var variable if you declare in class body and not initialized in init {} body then

you have to do the initialization in all of the constructors you have in class

only if not linked/invoked within class see example below else you will be in trouble

class A{
lateinit var i:String
init {
//i="10"
}
fun see(){
println("fi:$i")
}
constructor(){  i="10"
println("ci:$i")
}
constructor(ii:String){  i=ii
println("ci:$i")
}
}

In case of linked primary constructor initializes it is fine else in all constructor

class A{
lateinit var i:String
init {
//i="10"
}
fun see(){
println("fi:$i")
}
constructor(){  i="10"
println("ci:$i")
}
constructor(ii:String) :this(){ // i=ii // not compulsory unless you have requirement as such any,as init it is done in primary constructor
println("ci:$i")
}
}

lateinit var variable applied only on Objects not on primitive type

error: ‘lateinit’ modifier is not allowed on properties of primitive types
lateinit var i:Int

/**
 * You can edit, run, and share this code. 
 * play.kotlinlang.org 
 */
class D{
    companion object{ 
        fun firstInit():Int{ 
            println("firstInit\n") 
            return 20
        }
        init{
             println("companion Init\n") 
        }
        //println("cb firstInit\n")
    }
    	var title1="title1 test"
        var title="ztd naaval class also".also(::println)
        constructor(title:String){
            this.title=title
            println("constructor title:${this.title}")
            var selected="2353 2014"
            if (!isMatch(selected)){
                println("go for check ")
            }else{
                println("not going for check ")
            }
        }
        init{
            title="chnage in init"
            println("D init:"+title)
        }
        
        private val jokerList = arrayOf("2014","2353")
     
     private fun isMatch(vin:String) : Boolean {
           return jokerList.contains(vin)
    }
     
    }
//println("first class")
fun main() {
     
     


    val sl=mutableListOf<String>("1","2","3")
    sl.add("apple")
    sl.add("naval")
    sl.add("app")
    val sl1 =arrayOf<String>("1","2","3")
    var chkstr="1"
    var chk= chkstr !in sl
    println("$chkstr is not in $sl is  $chk")
    chkstr="0"
    chk= chkstr in sl
    println("$chkstr is in $sl is  $chk")
    val list=mutableListOf<Int>(2)
    list[0]=1
    try{    
        val i=list[-1]
    }catch(e:Exception){
        println("Exception:${e.message} :$list ")
    }
    data class P1(val name:String)
    data class P2(val i:Int)
     
    var p1 :P1? = P1("naval")
    //p1=null
    p1?.let{
        println("null case ${it}")
    }
    var a=ArrayList<Int>()
    a.add(1)
      a.add(12)
      a.addAll(ArrayList<Int>().apply{ this.add(3)})
      println(a.toString())
    val res=(p1 as? P2)
    println("Hello, world!!! res:${res} contains:${p1?.name?.contains("VA")}")
    val d= D("ztf")
    println("main fun title of D is called:"+d.title)
    
    
}

https://devhints.io/kotlin

By navalkishorjha

CustomView or Canvas Draw

https://programmer.help/blogs/android-custom-view-tool-paint-canvas-1.html

https://stackoverflow.com/questions/60232560/sweepgradient-android-how-to-set-start-angle-for-gradient

https://stackoverflow.com/questions/9037108/android-how-to-draw-an-arc-based-gradient

Animation of view draw line with slow animation

https://proandroiddev.com/android-bring-life-to-your-custom-view-8604ab3967b3

https://stackoverflow.com/questions/47655960/how-to-do-canvas-path-animation

https://stackoverflow.com/questions/18616035/how-to-animate-a-path-on-canvas-android

https://stackoverflow.com/questions/12037709/how-to-draw-a-path-on-an-android-canvas-with-animation

https://github.com/Audhil/GraduallyLinearLineGrowth/blob/master/src/com/wordpress/smdaudhilbe/view/GradualGrowingLine.java

https://www.programcreek.com/java-api-examples/?code=Brave-wan/SmartRefresh/SmartRefresh-master/refresh-layout/src/main/java/com/scwang/smartrefresh/layout/header/bezierradar/RoundProgressView.java

https://github.com/developer-shivam/PentagonFloatingActionButton/blob/master/app/src/main/java/developer/shivam/lifesumfloatingactionbutton/MainActivity.java

https://riptutorial.com/android/example/15665/valueanimator

https://android.developreference.com/article/11136617/How+to+draw+equidistant+dashes+using+DashPathEffect

https://stackoverflow.com/Questions/6103713/how-do-i-make-a-dotted-dashed-line-in-android

http://useof.org/java-open-source/android.graphics.DashPathEffect

By navalkishorjha

Fragment

Examples to explain the behaviour of a fragment with and without addToBackStack

Fragment and Activity lifecycle

images.jpeg

Option 1 – “addToBackStack()” is never used

Case 1A – adding, removing, and clicking Back button

Activity :      onCreate() - onStart() - onResume()                             Activity is visible
add Fragment A :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment A is visible
add Fragment B :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment B is visible
add Fragment C :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment C is visible
remove Fragment C :     onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Fragment B is visible
(Back button clicked)
Activity :      onPause() - onStop() - onDestroy()
Fragment A :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()
Fragment B :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               App is closed, nothing is visible

Case 1B – adding, replacing, and clicking Back button

Activity :      onCreate() - onStart() - onResume()                             Activity is visible
add Fragment A :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment A is visible
add Fragment B :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment B is visible
(replace Fragment C)    
Fragment B :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               
Fragment A :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()
Fragment C :        onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment C is visible
(Back button clicked)
Activity :      onPause() - onStop() - onDestroy()
Fragment C :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               App is closed, nothing is visible

Option 2 – “addToBackStack()” is always used

Case 2A – adding, removing, and clicking Back button

Activity :      onCreate() - onStart() - onResume()                             Activity is visible
add Fragment A :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment A is visible
add Fragment B :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment B is visible
add Fragment C :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment C is visible
remove Fragment C :     onPause() - onStop() - onDestroyView()                              Fragment B is visible
(Back button clicked)
Fragment C :        onCreateView() - onActivityCreated() - onStart() - onResume()                   Fragment C is visible
(Back button clicked)
Fragment C :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Fragment B is visible
(Back button clicked)
Fragment B :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Fragment A is visible
(Back button clicked)
Fragment A :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Activity is visible
(Back button clicked)
Activity :      onPause() - onStop() - onDestroy()                              App is closed, nothing is visible

Case 2B – adding, replacing, removing, and clicking Back button

Activity :      onCreate() - onStart() - onResume()                             Activity is visible
add Fragment A :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment A is visible
add Fragment B :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment B is visible
(replace Fragment C)    
Fragment B :        onPause() - onStop() - onDestroyView()  
Fragment A :        onPause() - onStop() - onDestroyView() 
Fragment C :        onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment C is visible
remove Fragment C :     onPause() - onStop() - onDestroyView()                              Activity is visible
(Back button clicked)
Fragment C :        onCreateView() - onActivityCreated() - onStart() - onResume()                   Fragment C is visible
(Back button clicked)
Fragment C :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               
Fragment A :        onCreateView() - onActivityCreated() - onStart() - onResume()   
Fragment B :        onCreateView() - onActivityCreated() - onStart() - onResume()                   Fragment B is visible
(Back button clicked)
Fragment B :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Fragment A is visible
(Back button clicked)
Fragment A :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Activity is visible
(Back button clicked)
Activity :      onPause() - onStop() - onDestroy()                              App is closed, nothing is visible

Option 3 – “addToBackStack()” is not used always (in the below examples, w/o indicates that it is not used)

Case 3A – adding, removing, and clicking Back button

Activity :      onCreate() - onStart() - onResume()                             Activity is visible
add Fragment A :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment A is visible
add Fragment B w/o:     onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment B is visible
add Fragment C w/o:     onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment C is visible
remove Fragment C :     onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Fragment B is visible
(Back button clicked)
Fragment B :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               
Fragment A :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Activity is visible
(Back button clicked)
Activity :      onPause() - onStop() - onDestroy()                              App is closed, nothing is visible

Case 3B – adding, replacing, removing, and clicking Back button

Activity :      onCreate() - onStart() - onResume()                             Activity is visible
add Fragment A :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment A is visible
add Fragment B w/o:     onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment B is visible
(replace Fragment C)    
Fragment B :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()   
Fragment A :        onPause() - onStop() - onDestroyView() 
Fragment C :        onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment C is visible
remove Fragment C :     onPause() - onStop() - onDestroyView()                              Activity is visible
(Back button clicked)
Fragment C :        onCreateView() - onActivityCreated() - onStart() - onResume()                   Fragment C is visible
(Back button clicked)
Fragment C :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               
Fragment A :        onCreateView() - onActivityCreated() - onStart() - onResume()                   Fragment A is visible
(Back button clicked)
Fragment A :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Activity is visible
(Back button clicked)
Activity :      onPause() - onStop() - onDestroy()                              App is closed, nothing is visible
OnBackPressedCallback(true) this will be block the user and you can handle action here
activity?.onBackPressedDispatcher?.addCallback(this, object : OnBackPressedCallback(true) {
    override fun handleOnBackPressed() {
        // in here you can do logic when backPress is clicked
        if(BuildConfig.DEBUG) {
            Log.i("TAG", " back pressed is blocked.")
        }
    }
})

OnBackPressedCallback(false) this will be not block the user and you can handle action here
activity?.onBackPressedDispatcher?.addCallback(this, object : OnBackPressedCallback(false) {
    override fun handleOnBackPressed() {
        // in here you can do logic when backPress is clicked
        if(BuildConfig.DEBUG) {
            Log.i("TAG", " back pressed is not blocked.")
        }
    }
})
By navalkishorjha

Thread & Coroutines

Usually, instances of classes that implement the Runnable interface is used to create threads in Kotlin. Because of the Runnable interface has just one method, the run() method, you can leverage Kotlin’s feature to create new threads with minimal boilerplate code.

Here’s how you can use the thread() function, which is a part of Kotlin’s standard library, to quickly create and start a new thread:

thread {
// long running operation goes here
}

The above approach is appropriate only when you need to occasionally spawn a thread or two.

If concurrency is an important part of your app’s business logic and you need a large number of threads, using thread pools with an executor service is a better idea.

For example, the following code uses the newFixedThreadPool() method of the Executors class to create a thread pool containing eight reusable threads and runs a large number of background operations on it:

val myService:ExecutorService = Executors.newFixedThreadPool(8)
var i = 0
 
while (i < items.size) {  // items may be a large array
val item = items[i]
myService.submit {
processItem(item) // a long running operation
}
 
i += 1
}

It might not be obvious at first glance but, in the above code, the argument to the submit() method of the executor service is actually a Runnable object.

Background tasks created using the Runnable interface cannot return any results directly. If you want to receive results from your threads, you must use the Callable interface instead, which is also a SAM interface.

When you pass a Callable object to the submit() method of an executor service, you receive a Future object. As its name suggests, the Future object will contain the result of the Callable at some point in the future, when the executor service has finished running it. To get the actual result from a Future object, all you need to do is call its get() method—but beware, your thread will block if you call it prematurely.

The following sample code shows you how to create a Callable object that returns a Future of type String, run it, and print its result:

val myService:ExecutorService = Executors.newFixedThreadPool(2)
 
val result = myService.submit(Callable {
// some background operation that generates
// a string
})
 
// Other operations
 
// Print result
Log.d(TAG, result.get())

Unlike Java, Kotlin doesn’t have the synchronized keyword. Therefore, to synchronize multiple background operations, you are expected to use either the @Synchronized annotation or the synchronized() standard library inline function. The annotation can synchronize an entire method, and the function works on a block of statements.

// a synchronized function
@Synchronized fun myFunction() {
 
}
 
fun myOtherFunction() {
 
// a synchronized block
synchronized(this) {
 
}
}

Both the @Synchronized annotation and the synchronized() function use the concept of monitor locks.

If you don’t already know, every object on the JVM has a monitor associated with it. For now, you can think of a monitor as a special token that a thread can acquire, or lock, to gain exclusive access to the object. Once an object’s monitor is locked, other threads that want to work on the object will have to wait until the monitor is released, or unlocked, again.

While the @Synchronized annotation locks the monitor of the object the associated method belongs to, the synchronized() function can lock the monitor of any object that’s passed to it as an argument.

Kotlin offers an alternative approach to achieve concurrency: coroutines. Coroutines are far lighter than threads and are much easier to manage.

In mobile multithreaded applications, threads are usually used for operations such as fetching information from the Internet or querying databases. Such operations don’t involve much computation, and the threads spend most of their lifetime in a blocked state, just waiting for data to come from somewhere else. As you can probably tell, that’s not a very efficient way to use the CPU.

Coroutines are designed to be used instead of threads for such operations. The most important thing you need to understand about coroutines is that they are suspendable. In other words, instead of blocking, they can simply stop when necessary and seamlessly continue later. This leads to much better CPU utilization. Indeed, with well-designed coroutines, you can effortlessly run dozens of background operations.

To be able to use coroutines in your Android Studio project, make sure you add the following compile dependency in the app module’s build.gradle file:

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1'

A coroutine can be suspended only with the help of a suspending function. Therefore, most coroutines have calls to at least one such function inside them.

To create a suspending function, all you need to do is add the suspend modifier to a regular function. Here’s a typical suspending function executing an HTTP GET request using the khttp library:

suspend fun fetchWebsiteContents(url: String):String {
return khttp.get(url).text
}

Note that a suspending function can be called only by a coroutine or another suspending function. If you try calling it from anywhere else, your code will fail to compile.

When it comes to creating a new coroutine, Kotlin’s standard library has enough coroutine builders to make you feel spoiled for choice. The simplest coroutine builder you can use is the launch() function, and like most other coroutine builders, it expects a suspending lambda, which is nothing but an anonymous suspending function. As such, this lambda is what becomes the coroutine.

The following code creates a coroutine that makes two sequential calls to the suspending function we created in the previous step:

val job1 = launch {
val url1 = fetchWebsiteContents("https://code.tutsplus.com")
val url2 = fetchWebsiteContents("https://design.tutsplus.com")
}

The return value of the launch() function is a Job object, which you can use to manage the coroutine. For example, you can call its join() method to wait for the coroutine to complete. Similarly, you can call its cancel() method to immediately cancel the coroutine.

Using the launch() function is much like creating a new thread with a Runnable object, primarily because you can’t return any value from it. If you want to be able to return a value from your coroutine, you must create it using the async() function instead.

The async() function returns a Deferred object, which, just like the Job object, allows you to manage the coroutine. However, it also allows you to use the await() function to wait for the result of the coroutine without blocking the current thread.

For instance, consider the following coroutines that use the fetchWebsiteContents() suspending function and return the content lengths of two different webpage addresses:

val jobForLength1 = async {
fetchWebsiteContents("https://webdesign.tutsplus.com").length
}
 
val jobForLength2 = async {
fetchWebsiteContents("https://photography.tutsplus.com").length
}

With the above code, both the coroutines will start immediately and run in parallel.

If you now want to use the returned lengths, you must call the await() method on both the Deferred objects. However, because the await() method too is a suspending function, you must make sure that you call it from another coroutine.

The following code shows you how to calculate the sum of the two lengths using a new coroutine created with the launch() function:

launch {
val sum = jobForLength1.await() + jobForLength2.await()
println("Downloaded $sum bytes!")
}

Coroutines do make use of background threads internally, which is why they don’t run on an Android app’s UI thread by default. Consequently, if you try modifying the contents of your app’s user interface from inside a coroutine, you will encounter a runtime error. Fortunately, it’s trivially easy to run a coroutine on the UI thread: you just have to pass the UI object as an argument to your coroutine builder.

For example, here’s how you can rewrite the last coroutine to display the sum inside a TextView widget:

launch(UI) {
val sum = jobForLength1.await() + jobForLength2.await()
myTextView.text = "Downloaded $sum bytes!"
}

The above code might seem mundane at first, but look again. It’s not only able to wait for two background operations to complete without using callbacks, it’s able to do so on the app’s UI thread without blocking it!

Having the ability to wait on the UI thread, without making your UI feel sluggish or triggering an Application Not Responding error, often referred to as ANR, simplifies a lot of otherwise complex tasks.

For instance, with the suspending delay() function, which is the non-blocking equivalent of the Thread.sleep() method, you can now create animations with loops. To help you get started, here’s a sample coroutine that increments the x coordinate of a TextView widget every 400 ms, thus creating a marquee-like effect:

launch(UI) {   
    while(myTextView.x < 800) {
        myTextView.x += 10
        delay(400)
    }
}

Always launch coroutines on the UI layer of your app (ViewModel, Activity, or Fragment) and tie them to its lifecycle by using the appropriate CoroutineScope.

Every other async function can simply be marked with suspend, to indicate that it needs to be called from a coroutine without actually creating one.

1. ViewModel

When launching coroutines from a ViewModel you can use viewModelScope

viewModelScope.launch {
// Coroutine ...
}

2. Activity

When launching coroutines from an Activity you can use lifecycleScope

lifecycleScope.launch {
// Coroutine ...
}

3. Fragment

When launching coroutines from a Fragment you can use viewLifecycleOwner.lifecycleScope

viewLifecycleOwner.lifecycleScope.launch {
// Coroutine ...
}

It is important to access the lifecycle scope of the viewLifecycleOwner to tie the coroutine to the Fragment’s View, instead of the Fragment itself.

4. App-wide Coroutines

Sometimes you might want a coroutine to complete regardless of its creator lifecycle. Some examples can be:

  • Syncing data between your server and the local storage.
  • Executing fire-and-forget requests to the backend.
  • Running periodic tasks.
  • Communicating with external services.

For those and other scenarios there are two solutions:

1. WorkManager
WorkManager is a Jetpack library that makes it easy to schedule deferrable and asynchronous tasks that are expected to run even if the app exits or the device restarts.

Implement the CoroutineWorker class on your Workers to gain access to the suspend function doWork().

Workers are queued using the WorkManager and therefore become independent to the current lifecycle.

You can learn more about WorkManager on the Android Developers Documentation.

2. Application Coroutine Scope
Create a new coroutine scope inside the Application class and inject it into the components that need it.

val appScope = CoroutineScope(SupervisorJob())

For this scope, ensure you create a SupervisorJob instead of a Job, to prevent cancelling all child coroutines when one fails.

This solution works well for simple one-off operations. For more complex or recurring tasks, however, use the WorkManager.

CoroutineContext: Choosing the right thread

Coroutines not only execute tasks in the background, but they can also run on the Main Thread.

The element that determines which Thread the coroutine uses is called CoroutineContext.

All coroutine builders accept an optional CoroutineContext parameter. The context (and thread) can also be changed during the coroutine execution by using the withContext(context) { … } block.

The easiest way to specify a coroutine context is by using the built-in Dispatchers class.
There are 3 Dispatchers you can use:

  • Main: For Main Thread operations.
  • IO: For Background operations that need to wait.
  • Default: For Background CPU-intensive tasks, where there is little or no sleep.

Example: To launch a coroutine that retrieves some data from an API and then updates a local list, launch the coroutine with the IO Dispatcher.
After receiving the response, switch back to the Main Thread to update the UI using the Main Dispatcher.

scope : above any 1,2 3 type is mentioned based on that scope can define.

scope.launch(Dispatchers.IO) {
val result = apiService.getListData()
withContext(Dispatchers.Main) {
adapter.submitList(result)
textview.text="hello"
}
}

This is very similar to launching a new Thread or AsyncTask and then using runOnUiThread { … } to update the UI.

Most 3rd party services like Ktor and Retrofit already support this behavior automatically by using the IO Dispatcher on all requests. In those cases, you can safely launch the coroutine on your current scope without specifying any context.

Testing Tip: Consider injecting Dispatchers instead of hardcoding them. This will help with Unit Testing your classes by using the TestCoroutineDispatcher() as your dispatcher for tests, to execute all coroutines synchronously.

 

Running coroutines sequentially

Running tasks sequentially means that we want to wait for each one to complete before moving to the next one. This is needed for example if the result of one task is used by the next one. For this purpose, withContext() is the ideal solution.

 





(1) is executed first and the first withContext() doesn’t return until (1) completes.
When (1) completes, we have the result in result1 and the second withContext() is executed. (2) can use the value available in result1 if needed. Again, given that withContext() is a suspend function, the parent coroutine is suspended until (2) completes. At that point, result2 will be available within the parent coroutine to continue with other operations.

Running coroutines in parallel

Running tasks in parallel means that they can run at the same time on separate threads making use of the multiple CPU cores available. This results in faster processing time because we don’t need to wait for one task to complete before moving to the next one. This is typically possible when the result of one task is not used by the next one. A good candidate to achieve this behaviour in the coroutines world is for sure async().

 

While developing Android apps, it is imperative that you perform long-running operations in background threads. In this tutorial, you learned several approaches you can follow to create and manage such threads in Kotlin. You also learned how to use the still experimental coroutines feature to wait inside threads without blocking them.

To learn more about coroutines, you can refer to the official documentation.

By navalkishorjha