Моя карьера началась как разработчик iOS, а недавно я начал руководить командами iOS и Android. Спустя несколько недель я не мог не заметить сходства между двумя платформами на уровне инфраструктуры.

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

Я собираюсь ориентироваться в основном на проекты iOS, в которых не используются раскадровки, я их не фанат. Начнем сначала с краткого обзора:

AppDelegate против MainActivity

Последние рекомендации по разработке Android продвигают использование одного класса активности и нескольких фрагментов (да, я знаю, что не все приложения построены таким образом, но, похоже, это последняя передовая практика для большинства случаев).

AppDelegate и MainActivity очень похожи, они оба являются «точкой входа» приложений и местом, где вы обычно должны размещать свои первые экземпляры приложения, или, если вы используете инъекцию зависимостей (и вы должны), это то место, где вы обычно запускаете его. .

iOS: AppDelegate
class AppDelegate: UIApplicationDelegate {
 func application(_ application: UIApplication, didFinishLaunchingWithOptions 
launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
 //Entry point (In case you do not use storyboards)
 }
}
Android: MainActivity
public abstract class MainActivity extends AppCompatActivity {
 protected void onCreate(Bundle savedInstanceState) {
 //Entry point
 }
}

UIViewController против фрагмента

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

Примечание. Я считаю само собой разумеющимся, что вы используете шаблон проектирования MVVM, поэтому оба класса содержат только элементы пользовательского интерфейса и связаны с некоторой ViewModel для обновления при изменении состояния приложения.

Назначение событий жизненного цикла очень похоже, но в UIViewController их гораздо больше. Например, ViewWillAppear будет срабатывать всякий раз, когда представление будет представлено на экране, ViewDidAppear сработает, когда представление будет представлено. Фрагменты не обладают этой способностью, вместо этого вам придется обойти это истинными способами.

Android: Fragment
class MyFragment: DialogFragment {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View? {
 //First allocations/inflate 
 //View setup will happen on "onViewCreated"
 }
}
iOS: UIViewController
class ViewController: UIViewController{
 override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
 super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
 //First allocations
 //Some programmers would use "ViewDidLoad" for this purpose
 }
}

UITableView против RecycleView

В первые дни iOS была известна своей высокой производительностью по сравнению с Android.
Это во многом связано с повторным использованием представлений для более быстрой прокрутки (60 кадров в секунду).
iOS использует UITableView с момента своего первого запуск. Чтобы быть более конкретным, iOS 2 (которая была первой iOS, которая поддерживала стороннее приложение через AppStore).
UITableView повторно использует свои ячейки (специфичное для платформы имя для элементов строк), потому что создание новых единицы, по одному для каждой прокрутки.
В CellForRawAtIndexPath вы получите новый или переработанный экземпляр текущей ячейки для каждого индекса и сможете настроить его представление.

Android, с другой стороны, сначала начал с компонента под названием «ListView», который страдал от отсутствия механизма повторного использования и низкой производительности.

«RecycleView» пришел на помощь на Google I / O 2014. Его название подразумевает, что он перерабатывает представления.
RecycleView использует адаптер (модель – представление – адаптер), который определяет, сколько элементов будет отображаться, какие типы элементов , раздувание (создание представлений из XML) и установка / привязка элементов с новыми представленными данными прокрутки.

RecycleView использует ViewHolder для хранения ссылки на созданные элементы, вместо того, чтобы создавать новые экземпляры (раздувая их), он повторно использует уже существующие.

iOS: UITableView
class MyViewController: UIViewController, UITableViewDelegate, UITableViewDataSource
{
 let tableView = UITableView.init()
override func viewDidLoad() {
  super.viewDidLoad()
  self.tableView.delegate = self
  self.tableView.dataSource = self
}
 
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
 //You will get passed a recycle cell, or a new one. 
 }
 func tableView(_ tableView: UITableView, numberOfRowsInSection  section: Int) -> Int{
//Number of rows displayed 
 }
}
Android: RecycleView
class MyFragment : DialogFragment {
 var adapter: MyAdaptor
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
 super.onViewCreated(view, savedInstanceState)
 homeRecycler.layoutManager = LinearLayoutManager(activity,    LinearLayoutManager.VERTICAL, false)
 homeRecycler.adapter = this.adapter
 }
}
class MyAdaptor : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
 var items: List<HomeFeedItem> = listOf()
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
 // Bind ViewHolder to current item props
  if (holder is MyViewHolder) {
    holder.bindViews(items[position])
    return
   }
 }
 override fun getItemViewType(position: Int): Int {
  return items[position].itemType().intValue()
 }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
 // This is the magic. Inflating will happen only once to improve performance
 val inflate: CardView =   LayoutInflater.from(context).inflate(R.layout.myLayout, parent,  false) as CardView
 return MyViewHolder(inflate)
 }
fun setFeed(items: List<HomeFeedItem>) {
 //Reload list modals 
 this.items = items
 this.notifyDataSetChanged()
 }
 override fun getItemCount() = items.size
}

Макет: ограничения XML VS

Сначала я скажу следующее: я был удивлен компоновкой Android, потому что она хорошо работает. Легко начать (особенно если у вас есть опыт веб-разработки).

Конструктор интерфейсов Android тоже отлично работает, отражая точное состояние XML, экономя много времени на компиляции.

iOS использует макет ограничения, так называемый «выраженный» способ определения макета с помощью кода (или раскадровки). У него большая кривая обучения, поскольку он не работает, как любой другой фреймворк (по крайней мере, который я использовал в прошлом), и имеет несколько важных тем, таких как приоритеты, поддержка контента, сопротивление сжатию и многое другое, которые довольно сложно понять. сначала обойдите вокруг.

По сути, ограничения - это объекты, которые определяют отношения между объектами пользовательского интерфейса и могут быть добавлены с помощью кода или Interface Builder.

Android, с другой стороны, использует XML-макет, очень похожий на некоторые популярные веб-фреймворки, и прекрасно работает с вашей IDE. Хотите цвет отступов / полей / фона? Не уверены в синтаксисе? Просто начните вводить текст, и Android Studio выполнит автозаполнение именно тем, что вы хотели.

В следующем сообщении в блоге я собираюсь затронуть следующие темы:

Dagger vs Swinject
Навигация по приложениям
Реализация MVVM

Подробнее откуда это взялось

Эта история публикуется в журнале Noteworthy, куда каждый день приходят тысячи людей, чтобы узнать о людях и идеях, формирующих наши любимые продукты.

Следите за нашей публикацией, чтобы увидеть больше историй о продуктах и ​​дизайне, представленных командой Журнала.