Android 개발은 재미있습니다. 의심의 여지가 없습니다. 그러나 반복적인 상용구 코드를 작성하도록 강요하는 플랫폼은 여전히 많습니다. 많은 경우 이는 작업이 필요한 UI 구성 요소와 관련이 있습니다. 애플리케이션 아키텍처를 깔끔하게 만들고 싶을 때 실제로 필요한 것이 있습니다. 실제로 백그라운드에서 많은 작업이 비동기적으로 발생하므로 읽을 수 없거나 옳지 않은 느낌이 드는 스파게티 코드 묶음으로 끝나기 쉽습니다.
오늘은 예제 프로젝트를 사용하여 코드를 명확하고 읽기 쉽게 유지하는 데 도움이 되는 6개의 Android 라이브러리를 살펴보겠습니다. 이를 통해 라이브러리의 기능을 확인할 수 있습니다.
프로젝트
이전에 Retrofit 가이드에서 사용했던 Retrofit 2 샘플 애플리케이션을 사용하겠습니다. 이는 GitHub에서 찾을 수 있는 간단한 오픈 소스 프로젝트입니다. 회사 이름과 Git 저장소가 필요하며 모든 기여자가 나열됩니다. 기여자는 아바타와 함께 목록으로 표시됩니다. 혁신적인 앱은 아니지만 네트워킹 수행, 이미지 작업, 목록 구성 요소 생성 및 사용자 입력 처리 방법을 보여줍니다. 이 모든 기능을 갖춘 장난감 프로젝트를 가지고 놀 수 있습니다.
주석 라이브러리를 코드에 적용하고 이것이 Android 앱 코드의 깔끔함을 유지하는 데 어떻게 도움이 되는지 살펴보겠습니다.
1.Butter Knife
코드에서 뷰에 액세스해야 할 때마다 해당 뷰의 개체 인스턴스를 가져와야 합니다. rootView.findViewById() 메서드를 작성한 다음 반환된 개체를 올바른 보기 유형으로 변환하면 됩니다. 그러나 코드는 빠르게 구축되지만 특히 onCreate 및 onCreateView 메소드에는 성가신 유사한 명령문이 있습니다. 생각해 보세요. onCreate 메서드에서 모든 것을 초기화하고 리스너를 바인딩하고 전체 UI를 하나로 묶습니다. UI 요소가 많을수록 단일 메서드의 시간이 길어집니다.
간단한 예를 들어보겠습니다.
이 뷰에는 3개의 뷰, 즉 두 개의 EditText와 버튼이 필요합니다. 이는 프래그먼트에서 참조해야 합니다. 일반적으로 다음과 같이 합니다.
@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View rootView = inflater.inflate(R.layout.fragment_search, container, false); companyEditText = (EditText) rootView.findViewById(R.id.company_edittext); repositoryEditText = (EditText) rootView.findViewById(R.id.repository_edittext); searchButton = (Button) rootView.findViewById(R.id.search_button); searchButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { searchContributors(); } }); return rootView; }
코드에는 레이아웃에서 뷰를 찾아 이를 액티비티 필드에 저장하고 익명의 내부 클래스를 리스너로 추가하여 검색 명령을 처리하는 것 외에는 별다른 작업이 없습니다. .많은 일이 일어나고 있습니다. Butter Knife를 사용하면 작업과 코딩이 더 쉬워집니다. 뷰 객체는 필드에 저장되므로 다음과 같이 각 필드에 Butter Knife @BindView 주석을 간단히 추가할 수 있습니다.
@BindView(R.id.company_edittext) EditText companyEditText; @BindView(R.id.repository_edittext) EditText repositoryEditText; @BindView(R.id.search_button) Button searchButton;
또한 onCreateView 메서드가 Butter Knife의 존재를 인식하도록 해야 합니다. 이제 초기화 코드에는 다음과 같은 짧은 문만 포함됩니다.
@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View rootView = inflater.inflate(R.layout.fragment_search, container, false); ButterKnife.bind(this, rootView); return rootView; }
한 단계 더 나아가 리스너를 searchButton 메서드에 바인딩하는 것을 건너뛰고 대신 onSearchButtonClicked 메서드에 주석을 달아 버튼 클릭에 마법처럼 바인딩할 수 있습니다. @OnClick 주석:
@OnClick(R.id.search_button) public void onSearchButtonClicked(View searchButton) { searchContributors(); }
공식 Butter Knife 홈페이지에는 다른 예도 있습니다. 하나씩 확인해 보세요! 일반적으로 프로그래밍 방식으로 뷰 요소에 액세스해야 하는 경우 Butter Knife를 사용하면 코드를 더 간결하고 읽기 쉽게 만들 수 있습니다.
2.Ice Pick
많은 Android 애플리케이션이 직면하는 일반적인 문제는 활동 및 프래그먼트 수명 주기를 잘못 처리하는 것입니다. 예, 우리는 이것이 Android 프레임워크에서 가장 멋진 부분이 아니라는 것을 알고 있습니다. 그러나 사용자가 기기를 옆으로 움직일 때 앱이 충돌하지 않도록 AndroidManifest 파일에서 가로 모드를 비활성화하는 것은 올바른 해결책이 아닙니다. 첫째, 다소 어리석은 것처럼 보이고 둘째, 코드가 구성을 처리하지 않기 때문입니다. 올바르게 변경됩니다. 여전히 발생하고 모든 것을 망칩니다! 따라서 애플리케이션 구성 요소의 상태와 수명 주기를 적절하게 처리해야 합니다.
구현 목적은 액티비티 내 모든 필드의 내용을 번들에 저장한 후, 안드로이드 프레임워크에 의해 라이프사이클을 통해 올바르게 관리하는 것입니다. 이것은 꽤 지루할 수 있습니다.
幸运的是,Ice Pick使我们的生活变得容易多了,因为你再不必一个个添加所有的变量到bundle去保存。同样从bundle中再次读取数据,如果存在,那么会很有挑战性,但Ice Pick简化了很多很多。因此,作为示例,假设我们需要记住最后一家公司和存储库搜索的组合。
首先,我们对要保存到bundle的字段进行注解。
@State String lastSearchCombination;
现在我们需要在onSaveInstanceState()方法中调用Ice Pick:
@Overridepublic void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); Icepick.saveInstanceState(this, outState); }
也在onCreateView()方法中调用Ice Pick来恢复状态:
@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View rootView = inflater.inflate(R.layout.fragment_search, container, false); ButterKnife.bind(this, rootView); Icepick.restoreInstanceState(this, savedInstanceState); return rootView; }
记住:你可以保存到bundle的内容的限制仍然存在。但是,没有必要因为为bundle键添加常量或为savedInstanceState添加空检查搞得一团乱。
3.Dart和Henson
与Ice Pick类似,Dart帮助我们避免为从一个活动传递到另一个活动的Intent Extras写入所有键和检查。它也适用于Fragments。这里有一个小例子,展示了我是如何使用@InjectExtra注释将搜索关键字从搜索屏幕传递到贡献者列表,实际上将执行搜索的地方。
所以我使用@InjectExtra注解定义了两个类变量:
@InjectExtra String repositoryQuery; @InjectExtra String companyQuery;
一旦Dart.inject(this, getActivity());被调用,那么这些都将会被自动初始化。现在在Bundle中被添加到Intent的extras最终将如何。你可以手动进行,但这里使用Henson是非常有道理的。为了使它工作,我添加以下代码到我的SearchFragment:
Intent intentContributorsFragment = Henson.with(getActivity()) .gotoContributorsFragment() .companyQuery(companySearchKeyword) .repositoryQuery(repositorySearchKeyword).build(); Intent intentContributorsActivity = Henson.with(getActivity()) .gotoContributorsActivity().build(); intentContributorsActivity.putExtras(intentContributorsFragment); startActivity(intentContributorsActivity);
这简化了代码中活动之间的通信,而无需每次都手动指定每个txtra。
4. Parceler
Parceler帮助你进行对象序列化。它可以帮助你传递任何对象作为Intent extra,而不会让你面对对象序列化的烦恼。
最好的事情是,Icepick,Henson和Dart也能很好地和Parceler一起玩。在我们的应用程序示例中,我使用@Parcel注释了我的Contributor类。这允许我使用Dart传递Contributor作为Intent Extra,使我的代码简洁和可读。
5.Timber
当我写代码的时候,过不了一会,我总有犯错误的倾向。通常情况下,这会导致应用程序的意外行为。我需要重现它,这样我才能解决这个问题。当你知道重现的步骤时,调试器会很方便,但是通常情况下,日志也包含了真相!
在Android中开箱即用的Log类足够好,因为可以提供不同的日志记录级别,等等。然而,每个Log.d()语句有两个参数;首先是tag,第二是message。99%的时间里,tag将是this.class.getName(),并且一次又一次地写会很烦人。幸运的是,使用Timber库,你只要这样做:
Timber.d("Informative output that needs to be logged.");
…并且它将为你提供正确的默认tag!此外,请记住,你需要在使用之前初始化Timber。查看我已添加调用的ContributorsApplication.onCreate()代码:
Timber.plant(new Timber.DebugTree());
这就是正确初始化Timber所有需要做的事情,所有没有理由你的app不使用Timber。
6.Dagger和Dagger2
最后,但并非最不重要的,Dagger和Dagger2库在app中管理依赖注入的表现真令人惊叹。为你处理依赖注入是编写代码的超棒做法。你指定应用程序的组件以及它们应如何相互交互。你可以定义代码的哪些部分需要其他部件的工作,瞧,这个库将为你初始化子部件,并根据需要注入它们。你可以检查示例项目代码以查看使用示例。
단, Dagger와 Dagger 2는 범위가 너무 넓어서 이번 글에서는 자세히 설명하지 않겠습니다. Dagger를 사용하고 싶다면 훌륭한 주석이 지원되는 훌륭한 코드 예제인 커피 메이커가 있습니다.
결론
흥미로운 Android 라이브러리가 많이 있지만 여기에는 몇 가지만 나열했습니다. 종속성만 지정하면 되므로 설치가 매우 쉽습니다. 이는 적극적으로 유지 관리되는 프로젝트이므로 훌륭한 문서가 있습니다.
빌드 프로세스에 주의를 기울이기만 하면 됩니다. 여러 라이브러리를 주석 프로세서와 결합하기 시작할 때 build.gradle에서 결합하는 대신 제공된() 또는 주석 처리기()를 사용해야 합니다.
코드를 더욱 깔끔하게 만들 수 있는 6가지 Android 라이브러리에 대한 자세한 내용은 PHP 중국어 웹사이트에서 관련 기사를 주목하세요!