Pro Android with Kotlin. Введение

Оглавление

Введение

Краткость против выразительности

Переход с Java на Kotlin

Целевая аудитория книги

Исходный код

Как читать эту книгу

Немного о синтаксисе коде в этой книге

Введение

Прошла уже пара лет с момента выхода первого издания этой книги. В первом издании рассказывалось о 8 версии Android и 26 уровне API. После этого времени уже вышла 9, 10, 11, 12, 13 и уже в апреле 2023 года мы знаем о том, что готовится к выпуску 14 версия ОС. IDE Android Studio также значительно изменило свою версию с 3.1 до Giraffe 2022.3.1(самая новая версия на 9 апреля 2023 года). Android Gradle плагин тоже сильно изменился с версии 3.1 до версии 8.2. Так же и Kotlin изменился с версии 1.2 до версии 1.8.20. В дополнение ко всему, android.support packages признан сейчас устаревшим и перенесен в Jetpack(https://developer.android.com/jetpack) под другим пространством имен. В первом издании книги, движок рендеринга 3D графики Vulkan был в зачаточном состоянии и поэтому не был включен в книгу. Однако за это время он приобрел все большую значимость и заметность, поэтому в Главе 9 про него добавлен раздел, который даст Вам отличное представление о том, что это.

В середине 2019 года Google презентовала Android Automotive – ответвление ОС Android, предназначенное для управления информационно-развлекательной системы автомобилей. С инструментом Jetpack Compose разработка UI стала гораздо проще и быстрее за счет использования сложных API “под капотом” и предоставления разработчику элегантного декларативного шаблона проектирования. Jetpack был представлен публике в 2018 году. Все эти изменения вошли во второе издание книги, чтобы Вы как Android разработчик были в курсе новейших тенденций,API и инструментов.

Краткость против выразительности

Весь исходный код и программы в этой книге написаны на языке программирования Kotlin. Однако это не означает, что если Вы пишете приложения под Android на языке Java или вообще знаете только Javascript или Swift, что Вам будет сложно понять и разобраться в коде. Главная цель, которая стояла при разработке языка Kotlin заключалась в выразительности и лаконичности языка, даже при уменьшении объема кода. Однако надо всегда помнить, что сокращение объема кода всегда сказывается на потере читабельности.

Когда встает вопрос что лучше, автор предпочитает выразительность краткости, но в мире профессионального программирования лучше делать выбор в пользу краткости. Потому что профессиональный программист всегда делает выбор в пользу краткости – так как код меньших объемов легче сопровождать.

Переход с Java на Kotlin

Для того, чтобы заинтересовать Вас, мы рассмотрим настоящее простое приложение, в котором не хватает некоторых функций, и затем сравним Java и Kotlin варианты исходного кода.

Запустите Android Studio и открыв мастер создания проекта, выберите шаблон – Basic Activity. Выберите минимальны API равный 23 и обязательно отключите поддержку Kotlin и устаревших библиотек поддержки. После создания проекта, откроется класс MainActivity. Рассмотрим Java код(комментарии удалены).

package book.andrkotlpro.frontjava;
import android.os.Bundle;
import com.google.android.material.snackbar.Snackbar;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import book.andrkotlpro.frontjava.databinding.    ActivityMainBinding;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends AppCompatActivity {
    private AppBarConfiguration appBarConfiguration;    
    private ActivityMainBinding binding;    

    @Override    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);        
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        setSupportActionBar(binding.toolbar);        
        NavController navController =  Navigation.findNavController(this, R.id.nav_host_fragment_content_main);        
        appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build();        
        NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);        
        binding.fab.setOnClickListener(new View.OnClickListener() {            
             @Override            
             public void onClick(View view) {                
                 Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG).setAction("Action", null).show();            
             } 
        });    
    }    
    
    @Override    
    public boolean onCreateOptionsMenu(Menu menu) {        
        getMenuInflater().inflate(R.menu.menu_main, menu);        
        return true;    
    }    

    @Override    
    public boolean onOptionsItemSelected(MenuItem item) {       
        int id = item.getItemId();
        if (id == R.id.action_settings) {            
           return true;        
        }        
        return super.onOptionsItemSelected(item);    
    }    

    @Override    
    public boolean onSupportNavigateUp() {        
        NavController navController =  Navigation.findNavController(this, R.id.nav_host_fragment_content_main);   
        return NavigationUI.navigateUp(navController, appBarConfiguration)|| super.onSupportNavigateUp();   
    }
}

Несколько заметок, касательно Java кода: ключевое слово public перед объявлением класса ставит область видимости класса MainActivity  доступной для всех , даже за пределами пакета. Его нельзя пропустить, так как в противном случае доступ к нему потеряет фреймворк и другие классы за пределами пакета. setContentView() благодаря “сеттеру” set,  является настолько распространенной конструкцией, что можно подумать о том, чтобы написать contentView = s.th вместо данной конструкции. Пара языков – конкурентов допускает такой синтаксис. Также можно использовать .onClickListener = s.th вместо громоздкой конструкции setOnClickListener(). А аргумент вызова setOnClickListener() – это анонимный класс, его можно сократить до:

binding.fab.setOnClickListener(        
     view -> {                
         Snackbar.make(view, "Replace with your own action",Snackbar.LENGTH_LONG).setAction("Action", null).show();            
     }    
);

Такая краткость достигается благодаря тому, что интерфейс имеет единственный метод. Мастер создания класса скорее всего не всегда может генерировать лямбда функции. Для различных вызовов .getSomething(), мы могли бы написать тоже что то вроде .something , что будет эквивалентно, но короче. Аналогичный проект, делающий то же самое, но написанный на языке Kotlin представлен ниже:

package book.andrkotlpro.frontkotlin
import android.os.Bundle
import com.google.android.material.snackbar.Snackbar
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import android.view.Menuimport android.view.MenuItem
import book.andrkotlpro.frontkotlin.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {    
    private lateinit var appBarConfiguration: AppBarConfiguration
    private lateinit var binding:  ActivityMainBinding    
    
    override fun onCreate(savedInstanceState: Bundle?) {        
        super.onCreate(savedInstanceState)        
        binding = ActivityMainBinding.inflate(layoutInflater)        
        setContentView(binding.root)        
        setSupportActionBar(binding.toolbar)
        val navController = findNavController( R.id.nav_host_fragment_content_main)        
        appBarConfiguration = AppBarConfiguration( navController.graph)        
        setupActionBarWithNavController(navController, appBarConfiguration)        
        binding.fab.setOnClickListener { view ->            
            Snackbar.make(view,  "Replace with your own action",  Snackbar.LENGTH_LONG).setAction("Action", null).show()        
        }    
    }    
   
    override fun onCreateOptionsMenu(menu: Menu): Boolean {        
        menuInflater.inflate(R.menu.menu_main, menu)        
        return true
    } 

    override fun onOptionsItemSelected(item: MenuItem):Boolean {        
       return when (item.itemId) {            
           R.id.action_settings -> true            
           else -> super.onOptionsItemSelected(item)        
       }    
    }  
 
     override fun onSupportNavigateUp(): Boolean {        
        val navController = findNavController(R.id.nav_host_fragment_content_main)        
        return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()    
     }
}

При внимательном рассмотрении Kotlin кода можно сделать следующие выводы:

  • мы не используем разделители  строки – “;” Kotlin  сам проверяет разрывы строк – завершен ли оператор или нужно включить следующую строку в текущее выражение
  • мы не используем ключевое слово public  в определении класса – модификатор “public” является модификатором по умолчанию в Kotlin
  • вместо написания extends(класс расширяет), мы указываем двоеточие, улучшая чтение кода.
  • не указываем тип возвращаемой функции как voidKotlin сам делает вывод что тип возвращаемой функции void
  • К сожалению мы не можем писать contentView = s.th, как мы предлагали выше, хотя язык Groovy, например, позволяет это. Причина, по которой мы не можем написать в языке Kotlin конструкцию contentView = s.th заключается в том, что компилятор подразумевает что должно быть поле класса contentView, что на самом деле не так. В теории компилятор мог бы проверить правильность написания методов и разрешить этот синтаксис, но разработчики Kotlin наложили ограничение и запретили конструкцию – когда поле не существует. Тоже самое справедливо и для вызова setOnClickListener, поскольку поле onClickListener не существует.
  • В отличии от использования анонимного класса, мы можем использовать возможности функционального программирование, используя конструкцию view -> .... Это возможно в том случае, если класс или интерфейс в нашем случае, содержит только один метод, например void onClick( View v ), в используемом здесь базовом интерфейсе. Компилятор Kotlin знает, что мы должны использовать этот конкретный единственный метод  интерфейса. В Java лямбда функции не были доступны до Java 8, в Kotlin же они доступны с самой первой версии. 
Подведем итог – исходный код класса на языке Kotlin занимает 1117 символов(включая пробелы и импорт) против Java кода с 1329 символами. В нашем случае это 17% экономии. Обычно 20-30% – это норма для более сложных проектов.
Несмотря на то, что синтаксис языков программирования Java и Kotlin отличаются, компилятор переводит что исходный код Java, что исходный код Kotlin в одни и те же байт конструкции для виртуальной машины Java. Поэтому разработчики на Kotlin могут без проблем использовать те же Java библиотеки, или из Java кода также вызывать классы и методы, написанные на Kotlin.

Целевая аудитория книги

Книга предназначена для Android разработчиков среднего и продвинутого уровней, которые хотят использовать возможности языка Kotlin для работы с текущими устройствами и версиями Android.

Читатели могут использовать Android Studio и язык Kotlin для создания продвинутых и качественных приложений для Android платформы.

Для чтения этой книги не обязательно быть экспертом по языку Kotlin, но иметь базовые знания в области программирования будет полезным. Онлайн документация по языку Kotlin также будет полезна Вам в изучении и чтении книги. 

Исходный код

Весь исходный код книги доступен по адресу https://github.com/timur-gaysin

Как читать эту книгу

Эту книгу вы можете читать последовательно, если Вы хотите получить полное представление о том, что Вы можете сделать на платформе Android. Или Вы можете читать главы независимо друг от друга, по мере работы над каким то проектом и желанием изучить новые темы. Также Вы можете использовать данную книгу в качестве справочника или если Вы хотите понять, как можно сделать те или иные решения, используя Kotlin код вместо Java кода. Сюда же входит описания специальных языковых конструкций Kotlin, которые помогут  сделать Ваш код более кратким и надежным.

Данная книга разбита по главам. Глава 1 представляет собой беглый осмотр системы Android с высоты птичьего полета. Если Вы уже знакомы с разработкой под Android, Вы можете пропустить эту главу.

Глава 2-6 рассказывает об основных архитектурных блоках Android: приложении в целом, активностях, сервисах, широковещательных приемниках и слушателях и проводниках контента. Разговаривая с читателем, как с профессиональным программистом мы можем честно сказать, что всю эту информацию можно легко найти на официальном сайте или куче других сайтов/книг. Главная причина, почему эта информация была добавлена – это обновление информации в соответствии с текущим статусом разработок и создания крепкой теоретической основы, к которой может обратиться читатель любого уровня. Также Вы можете обращаться к этой справочной информации, если по мере работы над каким – либо проектом Вы сталкиваетесь с трудностями, связанным с пробелами в понимании архитектуры приложения.

Глава 7 рассказывает о система разрешений, с который Вы как профессиональный разработчик тоже должны быть знакомы.
Главы 8-9 описывают API, которые вы можете использовать в своем приложении и при разработке пользовательского интерфейсе. Так как эти 2 темы являются достаточно большими, чтобы им выделить отдельную книгу, невозможно в этих 2-х главах упомянуть все вопросы. Однако, Вы можете найти интересные решения и возможности в этой области,  для создания Ваших приложений.

Глава 10 знакомит Вас с Firebase – облачное приложение, предоставляющее разработчикам самые широкие возможности, включая расширенное логирование, хранилище данных, баз и сервисы отправки и приема сообщений

Главы 11-12 знакомит нас со стратегией разработки приложений и также описывает, как это сделать лучше всего, используя язык Kotlin. В предыдущих главах Kotlin был представлен больше эмпирически, в то время как начиная с главы 11, мы покажем как создавать более элегантный и читабельный код.

Глава 13 посвящена обмену данными, а именно – описываются некоторые методы для обменом данными между компонентами Вашего приложения или с другим приложением или вообще в пределах этого мира.

Глава 14 знакомит нас с различными Android устройствами, такие как смартфоны, часы, Android TV и Android Auto. Также здесь мы покажем как получить доступ к камере и сенсорам и как мы можем вмешиваться в телефонные звонки.

В главах 15-18 мы рассмотрим тестирование, отладку, исправление ошибок и публикацию Вашего приложения. Наконец, в главе 19 объясняется как использовать инструменты разработчика, которые поставляются в комплекте SDK(или Android Studio)

Немного о синтаксисе кода в этой книге

Хотя в книге мы придерживаемся подхода – “чистого кода”, мы используем 2 анти-паттерна, которые применять в повседневной разработке не стоит:

  • Мы не используем локализованные ресурсы, поэтому Вы можете увидеть что то вроде
    android:text = "Some message"

    Вместо этого Вы должны использовать подход по размещению всех текстовых ресурсов в формате XML:

    android:text = "@string/message"

     

  • Для отображения логов, мы обычно используем LOG как тэг
    Log.e("LOG", "The message")

    В вашем коде Вы всегда должны использовать тэг, который отображает логируемый Вами класс:

    companion object {  val TAG="The class name"  ...}
    ...
    
    
    Log.e(TAG, "The message")

     

Leave a Reply

Please disable your adblocker or whitelist this site!