О чем писать, когда писать не о чем. Вебинар WebPromoExperts #290
Как писать под Android программы, а не код
Transcript of Как писать под Android программы, а не код
Beanpublic class StoryTeller { private int imageId; private String name; public StoryTeller(int imageId, String name) { this.imageId = imageId; this.name = name; } public int getImageId() { return imageId; } public void setImageId(int imageId) { this.imageId = imageId; } public int getName() { return name; } public void setName(String name) { this.name = name; } }
Bean + Lombok
@AllArgsConstructor(suppressConstructorProperties = true) public class StoryTeller { @Getter @Setter private int imageId;
@Getter @Setter private String name; }
Bean + Lombok
@Data @AllArgsConstructor(suppressConstructorProperties = true) public class StoryTeller { private int imageId; private String name; }
Lombok
buildscript { dependencies { classpath 'com.jimdo.gradle:gradle-apt-plugin:0.5' ... } }
apply plugin: 'apt'
dependencies { provided "org.projectlombok:lombok:1.12.6" apt "org.projectlombok:lombok:1.12.6" ... }
RxJava + Java 6articleSubscription.add(service.getNewsById(articleId) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .onErrorReturn(new Func1<Throwable, SingleNewsItem>() { @Override public SingleNewsItem call(final Throwable throwable) { LOGGER.error("Error while fetching the article with id = " + articleId); Toast.makeText(getActivity(), R.string.error, Toast.LENGTH_LONG).show(); hideProgressBar(); return null; } }) .subscribe(new Action1<SingleNewsItem>() { @Override public void call(final SingleNewsItem newsItem) { article = newsItem; articleView.loadData(article.getContent(); hideProgressBar(); } }));
RxJava + Java 6 + RetroLambda
articleSubscription.add(service.getNewsById(articleId) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .onErrorReturn(throwable -> { LOGGER.error("Error while fetching the article with id = " + articleId); Toast.makeText(getActivity(), R.string.error, Toast.LENGTH_LONG).show(); hideProgressBar(); return null; }) .subscribe(newsItem -> { article = newsItem; articleView.loadData(article.getContent()); hideProgressBar(); }));
Java 6 + RetroLambda
buildscript { dependencies { classpath 'me.tatarka:gradle-retrolambda:2.2.3' ... } }
apply plugin: 'retrolambda'
android { compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } ... }
RxJava
• Реактивное программирование — очень ок
• Экономит время на:• повторяющихся операциях• цепочках операций• группах параллельных операций• взаимодействиях потоков
Event Bus
• Делаем приложение слабо связным
• Развязываем руки как «производителям», так и «потребителям»
• Дешёвый аналог BroadcastListener
Otto — через аннотации
public class BaseFragment extends Fragment { protected Bus bus = MyApplication.getBus();
@Override public void onResume() { super.onResume(); bus.register(this); }
@Override public void onPause() { bus.unregister(this); super.onPause(); }
@Subscribe public void onResponse(WelcomeData data) { loadWelcome(data); } }
GreenDroid EventBus — по конвенции
public class BaseFragment extends Fragment { protected EventBus bus = EventBus.getDefault();
@Override public void onResume() { super.onResume(); bus.register(this); }
@Override public void onPause() { bus.unregister(this); super.onPause(); }
public void onEvent(WelcomeData data) { loadWelcome(data); } }
Layouts and Views
• findViewById — скучно и многословно.
• ButterKnife — аннотируем поля класса, устанавливаем автоматически.
• AndroidQuery — всё в одном, более лаконичные средства для простой работы со View
Layouts and Views
TextView view = (TextView)findViewById(R.id.text); view.setText("Hello");
// становится
new AQuery(this).id(R.id.text).text("Hello");
Layouts and Views
class ExampleActivity extends Activity { private TextView title; private TextView subtitle; private TextView footer;
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.simple_activity); title = (TextView)findViewById(R.id.title); subtitle = (TextView)findViewById(R.id.subtitle); footer = (TextView)findViewById(R.id.footer); }}
Layouts and Views
class ExampleActivity extends Activity { @InjectView(R.id.title) TextView title; @InjectView(R.id.subtitle) TextView subtitle; @InjectView(R.id.footer) TextView footer;
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.simple_activity); ButterKnife.inject(this); } }
Dependency Injection• Связывать части приложения будет легче и удобнее.
• Стандарт де-факто — Dagger
• Части приложения (модули) — будут связаны за нас.
• Синглтоны — за нас.
• Легко подменять модули.• Легко делать mock-модули.
JVM-based языки
• Scala, Clojure, тысячи их.
• Главное — генерировать байткод Java 6.
• И не использовать те фишки, которые Android из Java 6 не взял.
Лучшее — враг хорошего
• При всех улучшениях и удобствах нужно контролировать bus factor.
• Все «нестандартные» компоненты могут со временем сломаться.
• Совместимость между ними не всегда хороша.