Рубрики
Без рубрики

Советы на миллиард долларов для каждого разработчика Android

Узнайте о шаблонах дизайна Android, должны знать библиотеки Android, а также о том, что можно и чего нельзя делать в мобильной разработке.

Автор оригинала: John Paul Seremba.

Архитектурные Узоры

Одна из самых важных вещей, на которой вам следует сосредоточиться при разработке приложения мирового класса,-это разделение задач. Полезно разделить и четко определить роли для каждого компонента в вашем приложении. Класс не должен быть многозадачным компонентом. Многие разработчики совершают ошибку, записывая почти весь свой код в Действие или Фрагмент . Любой код, который не обрабатывает взаимодействие с пользовательским интерфейсом или операционной системой, не должен находиться в этих классах.

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

Существует несколько архитектурных моделей, но наиболее популярными являются;

  • MVC (Контроллер представления модели)
  • MVP (Ведущий представления модели)
  • MVVM (Модель представления ViewModel)

Я собираюсь небрежно представить каждый из вышеперечисленных архитектурных шаблонов.

i. MVC (Активная модель)

MVC обычно известен как активная модель. Модель уведомляет представление, когда оно изменяется контроллером.

кредит: codeproject.com

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

кредит: update.github.io

Модель: Это уровень данных. Он отвечает за управление бизнес-логикой и запросами API сети или базы данных.

Просмотр: Это уровень пользовательского интерфейса. Отвечает за визуализацию пользовательского интерфейса. Он отвечает за визуализацию данных из модели данных.

Контроллер: Это логический уровень. Он получает уведомление о поведении пользователя и соответствующим образом обновляет представление. Он также отвечает за обновление модели по мере необходимости. Для получения дополнительной информации о MVC, этот блог вас освещал.

ii. MVP (Ведущий представления модели)

Это также известно как пассивная модель . Ведущий-это единственный класс, который управляет моделью. Модель не уведомляет представление, когда оно изменяется ведущим. Уведомление осуществляется ведущим. Таким образом, модель называется неактивной или пассивной.

Модель-Вид-Контроллер — пассивная модель поведения (кредит: upday.github.io)

Модель: Это похоже на то, что мы определили выше. Это уровень данных, отвечающий за управление бизнес-логикой и запросами API сети или базы данных.

Просмотр: Это отвечает за представление данных способом, выбранным докладчиком. Представление обычно реализуется Действиями или Фрагментами.

Ведущий: Ведущий выступает в качестве связующего звена между моделью и представлением. Здесь должна быть определена вся логика представления. Он отвечает за запрос модели и обновление представления. Он также отвечает за реагирование на взаимодействие с пользователем и соответствующее обновление модели.

Этот архитектурный шаблон направлен на обеспечение того, чтобы вид выполнял как можно меньше работы. Другими словами, мы должны сделать вид как можно более тупым.

Ведущий также должен быть независимым от фреймворка и не должен зависеть ни от каких классов Android. Это должен быть простой класс POJO.

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

Пример реализации MVP;

Вот несколько примеров фрагментов кода из приложения simple stories.

Файл контракта-это файл интерфейса, содержащий презентер и просмотр интерфейсов. Интерфейс view предоставляет методы, которые отвечают за рисование пользовательского интерфейса, в то время как интерфейс presenter содержит методы, которые отвечают за логику выполнения, не зависящую от платформы Android. Он также содержит методы, которые извлекают данные для отображения в пользовательском интерфейсе.

Ниже показано, как файл контракта Контракт на фрагмент истории структурирован.

public interface StoriesFragmentContract {
  interface View {
    // methods for rendering the UI
    void showLoading();
    void hideLoading();
    void displayStories(List storiesList);
    void displayNoStories();
    void showError();
  }

  interface Presenter {
    // methods that contain business logic
    void setView(StoriesFragmentContract.View view);
    void getAndDisplayStories();
    void pullToRefreshStories();
  }
}

Контракт на фрагмент истории || структурирован.

Файл презентатора реализует интерфейс презентатора. Интерфейс докладчика определяет бизнес-логику приложения.

public class StoriesFragmentPresenter implements StoriesFragmentContract.Presenter {
  private StoriesFragmentContract.View mView;
  
  @Override public void setView(StoriesFragmentContract.View view) {
    mView = view;
  }

  @Override public void getAndDisplayStories() {
    List storiesList = new ArrayList();
    view.showLoading();
    
    // Logic for getting stories
    
    view.displayStories(storiesList);
    view.hideLoading();
  }

  @Override public void pullToRefreshStories() {
    // Logic for updating displayed stories
  }
}

Интерфейс докладчика определяет бизнес-логику приложения.

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

public class StoriesFragment extends Fragment implements StoriesFragmentContract.View {

  // declare your layout widgets
  private RecyclerView recyclerView;
  private ProgressBar progressBar;
  private LinearLayout error_layout;
  
  private StoriesAdapter adapter;
  private StoriesFragmentPresenter presenter;

  public StoriesFragment() {
    // Required empty public constructor
  }

  public static StoriesFragment newInstance() {
    StoriesFragment fragment = new StoriesFragment();
    return fragment;
  }

  @Override public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
  }

  @Override public View onCreateView(LayoutInflater inflater, ViewGroup container,
      Bundle savedInstanceState) {
    // inflate the fragment layout view
    View view = inflater.inflate(R.layout.fragment_stories, container, false);
    // provide view to the presenter
    presenter.setView(this);
    return view;
  }

  @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    // Code for UI Binding
    recyclerView = (RecyclerView) view.findViewById(R.id.stories_recycler);
    progressBar = (ProgressBar) view.findViewById(R.id.storiesLoadingProgressBar);
    error_layout = (LinearLayout) view.findViewById(R.id.stories_error_layout);
    recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
    
    // Call to the presenter to provide stories
    presenter.getAndDisplayStories();
  }

  @Override public void showLoading() {
    progressBar.setVisibility(View.VISIBLE);
  }

  @Override public void hideLoading() {
    progressBar.setVisibility(View.GONE);
  }

  @Override public void displayStories(List storiesList) {
    recyclerView.setVisibility(View.VISIBLE);
    adapter = new StoriesAdapter(storiesList, getContext());
    recyclerView.setAdapter(adapter);
  }

  @Override public void displayNoAssignments() {
    error_layout.setVisibility(View.VISIBLE);
  }

  @Override public void showError() {
    error_layout.setVisibility(View.VISIBLE);
  }

}

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

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

iii. MVVM (Модель представления ViewModel)

Это очень полезный шаблон, который был представлен вместе с компонентами архитектуры Android //. С помощью класса ViewModel этот шаблон позволяет вашему приложению выдерживать изменения конфигурации, возникающие в результате изменения ориентации устройства. Это связано с тем, что он сочетает в себе преимущества разделения задач, предоставляемые MVP, при одновременном использовании преимуществ привязки данных. С помощью этого шаблона модель выполняет как можно больше операций, сводя к минимуму логику в представлении.

В отличие от MVP, где ведущий содержит ссылку на представление, ViewModel не нужно содержать ссылку на представление, поскольку оно предоставляет потоки событий, к которым могут привязываться представления. Представление, однако, имеет ссылку на ViewModel, но ViewModel не имеет информации о представлении, следовательно, принцип; Потребитель данных должен знать о производителе, но производитель ( ViewModel ) не знает о том, кто потребляет данные.

Основными участниками здесь являются;

кредит: кредит:

Модель: Это также называется Моделью данных. Его основная цель-абстрагировать источник данных. ViewModel работает с Моделью данных

Просмотр: Задача этого компонента состоит в том, чтобы информировать модель представления о действиях пользователя. Он также отвечает за рисование пользовательского интерфейса. В рамках Android это может быть Активность или Фрагмент . В этом не должно быть никакой логики. Любая лежащая в основе логика должна обрабатываться ViewModel .

Модель представления: Этот компонент отвечает за предоставление потоков данных, относящихся к Представлению. Он извлекает данные из модели, применяет логику пользовательского интерфейса, а затем предоставляет соответствующие данные для использования представлением.

Самым большим плюсом вышеприведенного шаблона является то, что он очень упрощает тестирование вашего приложения. Модульные тесты можно легко написать для ViewModel , а тесты Эспрессо для View также легко выполнить. Это широкая модель, которая не может быть полностью представлена здесь. Более подробную информацию об этом же можно найти здесь .

Библиотеки

Бен Якубен в своем посте о библиотеках Android четко заявляет, что;

” Хороший разработчик знает, что никогда не изобретайте велосипед, если только вы не планируете узнать больше о колесах!”

Существует множество библиотек с открытым исходным кодом, которые разработчики могут свободно использовать в своих приложениях. Некоторые из них настолько полезны, что вам не следует запускать ни одно приложение без них. Одной строки кода в файле build.gradle вашего приложения достаточно, чтобы автоматически включить любую выбранную библиотеку. Ниже я собираюсь небрежно представить некоторые библиотеки must know, которые делают вашу жизнь в области разработки Android веселой и намного проще.

1. Переоборудование

кредит: кредит:

Это моя любимая библиотека. Это лучшая библиотека для выполнения вызовов REST API. Он упрощает HTTP-запросы с помощью аннотаций и автоматически обрабатывает синтаксический анализ JSON с помощью классов POJO. Все, что вам нужно сделать, это определить интерфейс API и класс дооснащения, который автоматически генерирует реализацию вашего интерфейса API. В своем интерфейсе вы используете аннотации для описания HTTP – запроса.

Простым примером интерфейса API является;

public interface GitHubService {
  @GET("users/{user}/repos")
  Call> listRepos(@Path("user") String user);
}

Простым примером интерфейса API является;

Класс дооснащения, который генерирует реализацию интерфейса службы Github , должен выглядеть следующим образом;

public class GithubApi {
  
  // Constructor to create the GithubApi
  public GithubApi() {
    this.createApi();
  }
  
  // Method that creates the Retrofit object
  private void createApi() {
    Gson gson = new GsonBuilder().create();
    Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.github.com/")
        .addConverterFactory(GsonConverterFactory.create(gson));
        .build();
    GitHubService service = retrofit.create(GitHubService.class);
  }
  
}

Класс дооснащения, который генерирует реализацию интерфейса || службы Github||, должен выглядеть следующим образом;

Я не буду так глубоко погружаться в тонкости реализации модернизации. Однако вы можете прочитать об этом здесь здесь ;

2. GSON

кредит: кредит:

В приведенном выше примере модернизации я представил GSON при создании Модернизация объект. Я думаю, вы задавались вопросом, почему! GSON-это библиотека, которая преобразует объекты Java (POJO) в их представление в формате JSON. Он также может быть использован для преобразования строки JSON в эквивалентный объект Java. Библиотека предоставляет простой toJSON() и FromJSON() методы преобразования объектов Java в JSON и наоборот. Однако при использовании Модифицируйте библиотеку , вам никогда не придется совершать прямые вызовы в GSON. Класс модернизации обрабатывает все это автоматически, когда вы добавляете GSON в качестве фабрики конвертеров . Более подробную информацию об этом же можно найти здесь .

3. Нож Для Масла

кредит: кредит:

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

Как правило, вы вызываете ссылки на представления в своем действии или фрагменте примерно так;

public class MainActivity extends AppCompatActivity {
  
  private TextView mWelcomeLabel;
  private EditText mUsernameField;
  private EditText mPasswordField;
  private Button mSubmitButton;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    
    mWelcomeLabel = (TextView) findViewById(R.id.welcomeLabel);
    mUsernameField = (EditText) findViewById(R.id.usernameField);
    mPasswordField = (EditText) findViewById(R.id.passwordField);
    mSubmitButton = (Button) findViewById(R.id.submitButton);
  }

}

Как правило, вы вызываете ссылки на представления в своем действии или фрагменте примерно так;

Однако, когда мы используем нож для масла, наш код становится гораздо более читабельным и кратким. Следовательно, один и тот же код действия должен выглядеть следующим образом;

public class MainActivity extends AppCompatActivity {
  
  @BindView(R.id.welcomeLabel) TextView mWelcomeLabel;
  @BindView(R.id.usernameField) EditText mUsernameField;
  @BindView(R.id.passwordField) EditText mPasswordField;
  @BindView(R.id.submitButton) Button mSubmitButton;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    
    ButterKnife.bind(this);
  }

}

MainActivity.java (ножом для масла)

Для получения дополнительной информации о ноже для масла обратитесь к документации по ножу для масла здесь .

4. Даггер2

кредит : Мерзкая Молния

Кинжал 2-это структура внедрения зависимостей, построенная на простой концепции, называемой инверсией управления. Согласно этой концепции, класс не должен настраивать свои зависимости статически, а должен быть настроен извне. В Java класс зависит от другого класса, если он использует экземпляр этого класса. Это называется зависимостью от класса.

Поскольку внедрение зависимостей в большинстве приложений мирового класса является обязательным, Dagger 2 является верным решением проблем, которые могут возникнуть при предоставлении зависимостей определенным классам. В идеале классы должны быть как можно более независимыми от других классов.

Кинжал 2 использует генерацию кода и основан на аннотациях. Сгенерированный код очень легко читается и отлаживается. Используемые аннотации: @Module , @Предоставляет , @Впрыснуть и @Компонент среди прочего.

Для получения дополнительной информации о внедрении зависимостей, Vogella поможет вам здесь .

5. Скользить

кредит: кредит:

Если вы уже использовали Picasso раньше, поверьте мне, Glide-лучший вариант для быстрой и эффективной загрузки изображений. Glide-это быстрая и эффективная платформа для управления мультимедиа и загрузки изображений, которая объединяет декодирование мультимедиа, кэширование памяти и дисков, а также объединение ресурсов в простой и удобный интерфейс.

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

Изображение или рисованный ресурс можно легко загрузить в просмотр изображений, просто позвонив;

GlideApp .with(CONTEXT) .load(URL) .into(IMAGE_VIEW);

Glide поддерживает извлечение, декодирование и отображение видеозаписей, изображений и анимированных GIF-файлов. Для получения дополнительной информации об этом же обратитесь к полной документации Glide здесь .

6. Комната

кредит: cdn-изображения

Для создания приложений мирового класса вам нужна чистая библиотека картографирования ORM. Комната была введена во время Google Ввод-вывод 2017 как библиотека сохранения, направленная на очистку архитектуры при разработке приложений для Android.

Комната в простых терминах-одна из лучших библиотек отображения объектов SQLite. Он обеспечивает уровень абстракции поверх SQLite, чтобы обеспечить свободный доступ к базе данных, используя при этом всю мощь SQLite.

Сохранение данных в автономном режиме значительно улучшает работу ваших пользователей в тех случаях, когда подключение к Интернету не работает. Цель каждого разработчика приложений-обеспечить пользователям беспрепятственный доступ к вашему приложению. Таким образом, пространство устраняет этот пробел, предоставляя самый простой механизм сохранения данных.

@Entity(tableName = "user")
public class User {
  @PrimaryKey(autoGenerate = true)
  private int userID;
  
  @ColumnInfo(name = "first_name")
  private String firstName;
  
  @ColumnInfo(name = "last_name")
  private String lastName;
  
  @ColumnInfo(name = "email")
  private String email;
  
  // getters and setters
  
}

Класс Модели пользователя

Вы можете найти более подробную информацию о номере здесь .

7. RxJava

кредит: кредит:

RxJava-одна из лучших библиотек для обеспечения возможности реактивного программирования в разработке Android. Это платформа для упрощения параллелизма или асинхронных задач. Многопоточность в большинстве случаев является проблемой для разработчиков, и если она не реализована правильно, это может привести к очень сложным ошибкам, которые необходимо исправить. RxJava приходит, чтобы облегчить вашу жизнь и помочь вам избежать неприятных утечек памяти.

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

public class MainActivity extends AppCompatActivity {
  
  // class attributes
  private Button mButton;
  
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    
    // activity configurations
    mButton = (Button) findViewById(R.id.user_details_btn);
    
    // make call to asyncTask
    mButton.setOnClickListener(new View.OnClickListener() {
      @Override public void onClick(View view) {
        new GetDataTask(1001).execute();
      }
    });
  }
  
  public class GetDataTask extends AsyncTask {
    private final int userId;
    
    public GetDataTask(int userId) {
      this.userId = userId;
    }
    
    @Override protected User doInBackground(Void... params) {
      return userService.getUserData(userId);
    }
    
    @Override protected void onPostExecute(User user) {
      // do something after getting user data
    }
  }
  
}

Выполнение сетевого вызова с помощью AsyncTask

Вышесказанное кажется безопасным подходом, но это не так. У него есть некоторые проблемы и ограничения. Утечки памяти/контекста легко создаются с помощью вышеуказанного подхода, так как GetDataTask является внутренним классом и содержит неявную ссылку на внешний класс. Несмотря на это, если вы хотите выполнить еще одну длительную операцию с возвращенными данными, это может привести к вложению другого AsyncTask , что значительно снижает читабельность.

Однако в случае RxJava выполнение одного и того же сетевого вызова может выглядеть следующим образом;

public class MainActivity extends AppCompatActivity {
  // class attributes
  private Subscription mSubscription;
  private Button mButton;
  
  @Override 
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    
    // activity configurations
    mButton = (Button) findViewById(R.id.user_details_btn);
    
    // make a network call
    mButton.setOnClickListener(new View.OnClickListener() {
      @Override public void onClick(View view) {
        mSubscription = userService.getObservableUser(1001)
          .subscribeOn(Schedulers.io())
          .observeOn(AndroidSchedulers.mainThread())
          .subscribe(new Action1() {
            @Override public void call(User user) {
              // do something with the user data
            }
          });
      }
    });
  }
  
  @Override protected void onDestroy() {
    if (mSubscription != null && !mSubscription.isUnsubscribed()) {
      mSubscription.unsubscribe();
    }
    super.onDestroy();
  }

}

Сетевой вызов с помощью RxJava

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

Для получения дополнительной информации о RxJava вы можете обратиться к этой потрясающей статье .

Чтобы статья была достаточно короткой, я остановлюсь на вышеперечисленных библиотеках. Но, вы можете прочитать об этом; Ciceron , хорошая библиотека навигации, Тонкий адаптер легкий, тонкий, чистый и типизируемый адаптер без необходимости в держателе просмотра и Анимация Android для Android |/библиотека среди многих.

Тесты

Разрабатывать приложение без тестов-все равно что ехать со скоростью 100 миль в час без ремня безопасности.

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

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

Вот шпаргалка эспрессо, которая сэкономит вам массу времени при написании тестов пользовательского интерфейса.

Что делать и чего не делать

кредит: кредит:

Делай,

  1. Дизайн для нескольких экранов
  2. Рассмотрите возможность поддержки нескольких языков
  3. Обеспечьте своим пользователям беспрепятственный пользовательский интерфейс
  4. Проведите тесты производительности
  5. Используйте инструменты аналитики пользователей
  6. Проводите мониторинг производительности и использования памяти

Не надо

  1. Разработайте для вас устройство
  2. Изобретение колеса
  3. Не использовать намерения
  4. Не используя фрагменты
  5. Блокирование основного потока
  6. Не предполагая успеха

Это то, что я считал советами на миллиард долларов для каждого разработчика Android. Надеюсь, вы хорошо прочитали.

Оригинал: “https://www.codementor.io/@johnpaulseremba/billion-dollar-tips-for-every-android-developer-fmcma9x7z”