05. Intents and Navigation

The three core components of applications: activates, services, and broadcast receivers, are all started through intents.

Intents can be used as a messaging system to activate components in the same application, or to start other applications.

Intents can be implicit or explicit:

Intents can return values to the activity which started it.

Some common intents: alarm clock, calendar, camera, contacts, app, email, file storage, maps, music, phone, search, settings.

TODO

startActivity startActivityForResult startService bindService

Android manifest:

Context.startActivity()
Activity.startActivityForResult() // expect a return value
Activity.setResult() // Set the return value to give to activtity that started the activity


Context.startService()
Context.bindService()
TODO

Intent object properties:

If your multi-screen app is a multiple-activity app, navigation can be achieved by using explicit intents TODO.

Navigation Architecture:

Recycler List Views

Generating views is expensive: list views only render the items that will be visible on the screen.

A recycler view is used to manage some backing data set and to re-use existing views as rows become hidden and visible.

data DataItem(val id: Int, val text: String)

class MainActivity: AppCompatActivity(), OnDataItemListener {
  private val data = arrayOf<DataItem>(
    DataItem(1, "Hello"),
    DataItem(2, "World"),
    DataItem(3, "Cat")
  )

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    val dataAdapter = DataAdapter(data)
    val recyclerView: RecyclerView = findViewById(R.id.recycler_view)
    recyclerView.adapter = dataAdapter
  }

  fun onItemClick(position: Int) {
    val intent = Intent(Intent.ACTION_WEB_SEARCH).apply {
      putExtra(SearchManager.QUERY, data[position])
    }
    if (intent.resolveActivity(packageManager) != null) {
      startActivity(intent)
    }
  }
}

class DataAdapter(private val data: Array<DataItem>,
                  private val listener: OnDataItemListener) :
      RecyclerView.Adapter<DataAdapter.DataItemViewHolder>() {



  // Make the class a subclass of RecyclerView, and call the superclass's
  // initializer with the `itemView` as the argument.
  // Also pass through the listener to each list item view holder
  private class DataItemViewHolder(itemView: View,
                                   private val listener: OnDataItemListener) :
                RecyclerView.ViewHolder(itemView) {
    val textView: TextView

    init {
      textView = itemView.findViewById("data_text")
    }

    override fun onClick(view: View?) {
      listener.onItemClick(adapterPosition)
    }
  }

  override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DataItemViewHolder {
    // parent context required as views need an owner
    val view = LayoutInflater.from(parent.context)
     .inflate(R.layout.list_item, parent, attachToRoot: false)
    // list_item.xml is a XML layout resource file for the list item

    return DataItemViewHolder(view, listener);
  }

  // Set view item content depending on element index
  override fun onBindViewHolder(viewHolder: DataItemViewHolder, position: Int) {
    viewHolder.textView = data[position].text;
  }

  override fun getItemCount() = data.size

  interface OnDataItemListener {
    fun onItemClick(position: Int)
  }
}

<!-- activity_main.xml -->
...
  <androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recyclerView"
    app:layoutManager=:LinearLayoutManager"
  />
  <!-- LinearLayoutManager = list view. grid view managers also available -->
...

<!-- list_item.xml -->
...
  <TextView
    android:id="@+id/data_text"
    android:text="Default Text"
  />
...