안드로이드 TV leanback 라이브러리 가져오기

이른바 leanback 라이브러리

  • Android Support Library 중 하나
  • TV 애플리케이션 개발 중 Google 가이드라인에 맞는 표준 UI/UX
  • 구현

    등장인물



    몇 개의 포장으로 나뉘었지만 이용자가 의식적으로 사용한 것은 appwidget로 정리되었다.

    app

  • Fragment
  • leanback의 UI는 Fragment 단위로 사용하기 때문에 기본적으로
  • 각각 Fragment와 Support Fragment을 준비했기 때문에 실질적으로 이곳의 절반 정도의 종류가 있다
  • 기본류 등도 포함되기 때문에 주로 몇 가지
  • 만 사용한다

    widget


    만약 대량이지만 이해해야 할 주요 부분만 주목한다면 이러한 분류는 다음과 같다
    각자의 역할에 관하여 다음 항목 이후에 서술하다
  • Adapter
  • Presenter
  • PresenterSelector
  • View
  • DataModel
  • Row
  • Action

  • 구조



    각 Fragment는 View의 중복 구조이기 때문에 인상으로 RecyclearView에 가깝다
    RecyclearView에 있는 View의 렌더링을 고려하면 어댑터의 직책 범위가 매우 넓다
    (그림1)

    따라서 예를 들어 데이터 종류별로 여러 가지 뷰를 분류하면 어댑터가 비대해진다
    (그림2)

    한편, leanback은 MVP 모델을 채택하여 View를 나타내는 부분에 대해 어댑터는Presenter로서 어댑터와 독립한다
    (그림 3)

    데이터의 종류를 보고 디스플레이를 전환하는 역할에 대해서도 전문적인 종류인'Preselector'를 준비했다
    따라서 어댑터의 역할은 다음과 같은 두 가지에 불과하다
  • 모든 유형의 데이터를 수신하고 등록된 Observer
  • 에 통지
  • 내부에서 수신된 데이터를 유지하고 외부에서 유지된 데이터 집합을 처리하는dd/remove/replace 등 작업
  • 그러나 거의 준비된 어댑터를 직접 사용하기 때문에 이용자들은 이를 거의 의식하지 못하고 실시한다
    각 뷰의 디스플레이 내용을 조정하려면 각 뷰와 해당 뷰를 처리하는 Presenter에만 집중하면 되므로 범위를 좁혀 수정할 수 있습니다.

    실제 이미지


    Google이 준비한 다음 샘플 코드를 기반으로 설치를 상상해 보십시오.
    여기에 배열 카드를 제작하고 수직으로 굴러가는 View를 만들기 위해app 봉인된 Framgent 중VerticalGridFragment
    leanback의 Fragment을 이용할 때 항상 다음과 같은 인상이 있어요.
    public class MyFragment extends VerticalGridFragment {
        ()
        setAdapter(Adapter);
        Adapter#add(DataA, DataB, DataC);
    
    Adapter는 중복된 간단한 데이터를 처리하기 위해 일반적으로 ArrayObjectAdapter를 사용합니다
    또한 図3에서 보듯이 어댑터는 Preselector를 포함하기 위해 어댑터에게
    그래서 위의 인상은 다음과 같다
    ArrayObjectAdapter adapter = new ArrayObjectAdapter(PresenterSelector);
    setAdapter(adapter);
    adapter.add(DataA, DataB, DataC);
    

    실제 소스 코드


    위의 인상에 따라 실제 소스 코드를 살펴보겠습니다.
    PresenterSelector cardPresenterSelector = new CardPresenterSelector(getActivity());
    ArrayObjectAdapter mAdapter = new ArrayObjectAdapter(cardPresenterSelector);
    setAdapter(mAdapter);
    
    String json = Utils.inputStreamToString(getResources().openRawResource(R.raw.grid_example));
    CardRow row = new Gson().fromJson(json, CardRow.class);
    mAdapter.addAll(0, row.getCards());
    
    PresenterSelector에서 Data의 종류에 따라 Presenter로 나뉜다(간단하기 때문에 일부분을 생략한다)
    public class CardPresenterSelector extends PresenterSelector {
        @Override
        public Presenter getPresenter(Object item) {
            Card card = (Card) item;
            switch (card.getType()) {
                case SINGLE_LINE:
                    presenter = new SingleLineCardPresenter(mContext);
                    break;
                case VIDEO_GRID:
                    presenter = new VideoCardViewPresenter(mContext, R.style.VideoGridCardTheme);
                    break;
                case MOVIE:
                case MOVIE_BASE:
                case MOVIE_COMPLETE:
                case SQUARE_BIG:
                case GRID_SQUARE:
                case GAME: {
                    presenter = new ImageCardViewPresenter(mContext, themeResId);
                    break;
                }
                case SIDE_INFO:
                    presenter = new SideInfoCardPresenter(mContext);
                    break;
                case TEXT:
                    presenter = new TextCardPresenter(mContext);
                    break;
                case ICON:
                    presenter = new IconCardPresenter(mContext);
                    break;
                case CHARACTER:
                    presenter = new CharacterCardPresenter(mContext);
                    break;
                default:
                    presenter = new ImageCardViewPresenter(mContext);
                    break;
            return presenter;
        }
    }
    
    마지막으로, 각 Presenter에 View를 표시합니다(단순하므로 일부를 생략함).
    public class ImageCardViewPresenter extends AbstractCardPresenter<ImageCardView> {
        @Override
        protected ImageCardView onCreateView() {
            ImageCardView imageCardView = new ImageCardView(getContext());
            return imageCardView;
        }
    
        @Override
        public void onBindViewHolder(Card card, final ImageCardView cardView) {
            cardView.setTag(card);
            cardView.setTitleText(card.getTitle());
            cardView.setContentText(card.getDescription());
            int resourceId = getContext().getResources().getIdentifier(card.getLocalImageResourceName(), "drawable", getContext().getPackageName())
            Picasso.with(getContext()).load(resourceId).into(cardView.getMainImageView());
        }
    }
    

    총결산


    이번에는 라이브러리에 등장하는 인물의 캐릭터를 이해하고 상상이 이루어지는 곳입니다.
    다음 이후에 상세히 설명하고 싶어요.

    좋은 웹페이지 즐겨찾기