Android scheme 점프 의 디자인 과 구현 에 대한 상세 한 설명

9856 단어 Androidscheme점프
발단
App 이 성장 함 에 따라 우 리 는 다음 과 같은 수 요 를 만 날 수 밖 에 없다.
  • H5 점프 네 이 티 브 인터페이스
  • 알림 클릭 조정 관련 인터페이스
  • 백 스테이지 에 따라 데이터 점프 인터페이스 로 돌아 갑 니 다.예 를 들 어 로그 인 성공 후 서로 다른 인터페이스 로 이동 하거나 운영 수요 에 따라 서로 다른 인터페이스 로 이동 합 니 다
  • AppLink 의 도약 실현
  • 이러한 문 제 를 해결 하기 위해 앱 은 일반적으로 scheme 전환 프로 토 콜 을 사용자 정의 하고 여러 측면 에서 이 프로 토 콜 을 실현 하여 각종 운영 수 요 를 해결한다.오늘 QMUI 최신 판QMUISchemeHandler의 디자인 과 구현 을 분석 해 보 겠 습 니 다.
    scheme 의 형식 은 대략 이 렇 습 니 다.
    schemeName://action?param1=value1¶m2=value2
    예 를 들 면:
    qmui://home?tab=2
    기술적 인 측면 에서 볼 때 scheme 의 도약 을 실현 하 는 것 은 결코 어 려 운 일이 아니다.바로 다음 두 단계 이다.
  • 분석 scheme
  • 분석 결과 에 따라 지정 인터페이스 로 전환
  • 그러나 코드 를 쓸 때 디자인 을 하지 않 으 면 if else 를 쌓 기 쉽다.예 를 들 면:
    
    if(action=="action1"){ 
     doAction1(params)
    }else if(action=="action2"){
     doAction2(params)
    }else {
     ...
    }
    새로운 scheme 이 추 가 될 때마다 if 를 추가 합 니 다.따라서 우 리 는 부지런히 생각 하고 재 구성 하 며 가능 한 한 빨리 좋 은 틀 을 설계 함으로써 자신의 두 손 을 해방 시 켜 야 한다.
    if else 와 같은 재 구성 에 있어 서 하나의 기본 적 인 방식 은 표 법 으로 모든 조건 과 실행 할 행 위 를 하나의 map 에 두 고 사용 할 때 이 map 를 조회 하여 실행 할 행 위 를 얻 는 것 이다.그리고 우 리 는 주 해 를 통 해 코드 생 성 방식 으로 이 맵 을 구축 하여 코드 의 작 성 량 을 줄 일 수 있 습 니 다.그 밖 에 우 리 는 각종 기능 적 수 요 를 고려 해 야 한다.
  • 차단기 interceptor 를 설정 할 수 있 습 니 다.예 를 들 어 일부 화면 을 뛰 어 넘 을 수 있 습 니 다.로그 인 하지 않 은 상태 라면 로그 인 인터페이스 로 뛰 어 넘 어야 할 수도 있 습 니 다
  • 매개 변 수 는 기본 형식 을 지정 할 수 있 습 니 다.scheme 이 가지 고 있 는 매개 변 수 는 모두 문자열 이지 만 우리 가 필요 로 하 는 기본 형식
  • 으로 편리 하 게 전환 되 기 를 바 랍 니 다.
  • 같은 action 은 매개 변수 에 따라 서로 다른 점프 행 위 를 할 수 있다.예 를 들 어 모두 책 을 뛰 어 넘 는 상세 한 상황 이다.만화 책 과 일반 책 이 뛰 어야 하 는 화면 이 다 를 수 있다
  • 현재 인터페이스 가 목표 인터페이스 라면 현재 인터페이스 리 셋 또는 새 인터페이스 시작
  • 을 선택 할 수 있 습 니 다.
  • QMUI 에 대해 Activity 와 Fragment 를 동시에 지원 하기 때문에 scheme 도 이 두 가 지 를 동시에 지원 해 야 한다
  • 새로운 인터페이스의 실례 화 방법 을 사용자 정의 할 수 있다
  • 인터페이스 디자인
    모든 라 이브 러 리 의 개발 은 업무 사용 자 를 안심 시 키 기 위해 라 이브 러 리 의 기능 이 충분 하고 사용 의 편리 성 을 확보 해 야 한다.QMUI Scheme 은 대외 적 으로 주로QMUISchemeHandler이라는 입구 류 와ActivitySchemeFragmentScheme두 개의 주해 이다.
    QMUISchemeHandlerQMUISchemeHandlerBuilder 모드 를 통 해 실례 화:
    
    //   schemeName
    val instance = QMUISchemeHandler.Builder("qmui://") 
     //              scheme  
     .blockSameSchemeTimeout(1000)
     // scheme    decode
     .addInterpolator(new QMUISchemeParamValueDecoder())
     .addInterpolator(...)
     //    fragment     factory
     .defaultFragmentFactory(...)
     //    activity     factory
     .defaultIntentFactory(...)
     //    scheme    
     .defaultSchemeMatcher(...)
     .build();
    
    if(!instance.handle("qmui://xxx")){ 
     // scheme    handle,    ?
    }
    대부분의 장면QMUISchemeHandler은 단일 모델 을 사용 하면 된다.여러 개의 차단 기 를 설정 하고 fragment,activity 의 기본 인 스 턴 스 화학 공장,그리고 기본 적 인 일치 기 를 설정 할 수 있 습 니 다.인 스 턴 스 공장 과 매 칭 기 는 모두 기본 적 인 실현 을 제공 하고 대부분 장면 은 호출 자의 관심 을 필요 로 하지 않 습 니 다.또한 전역 기본 값 만 설정 하고 scheme 주석 층 에 도착 하면 모든 scheme 에 다른 값 을 지정 하여 사용자 정의 수 요 를 만족 시 킬 수 있 습 니 다.
    Activity Scheme 과 Fragment Scheme 주해
    이 두 주 해 는 매우 비슷 하지만,Fragment 는 독립 되 었 기 때문에 더 많은 설정 항목 이 있 기 때문이다.
    
    @Retention(RetentionPolicy.CLASS)
    @Target(ElementType.TYPE)
    public @interface ActivityScheme { 
     // scheme action  
     String name();
     //        ,        action      scheme    ,      "type=4"     ,    "type"      
     String[] required() default {};
     //          scheme       ,          ,           ActivitySchemeRefreshable
     boolean useRefreshIfCurrentMatched() default false;
     //       scheme        ,     QMUISchemeMatcher    
     Class<?> customMatcher() default void.class;
     //       Activity     ,    QMUISchemeIntentFactory
     Class<?> customFactory() default void.class;
     //        ,   int/bool/long/float/double       ,      string   
     String[] keysWithIntValue() default {};
     String[] keysWithBoolValue() default {};
     String[] keysWithLongValue() default {};
     String[] keysWithFloatValue() default {};
     String[] keysWithDoubleValue() default {};
    }
    
    
    @Retention(RetentionPolicy.CLASS)
    @Target(ElementType.TYPE)
    public @interface FragmentScheme { 
     //        ActivityScheme
     String name();
     String[] required() default {};
     Class<?> customMatcher() default void.class;
     String[] keysWithIntValue() default {};
     String[] keysWithBoolValue() default {};
     String[] keysWithLongValue() default {};
     String[] keysWithFloatValue() default {};
     String[] keysWithDoubleValue() default {};
    
     //  ActivityScheme,   UI     FragmentSchemeRefreshable
     boolean useRefreshIfCurrentMatched() default false;
    
     //   ActivityScheme,      QMUISchemeFragmentFactory     
     Class<?> customFactory() default void.class;
     //        Fragment   activity   ,     activity      ,   activities          activity
     Class<?>[] activities();
     //          Activity
     boolean forceNewActivity() default false;
     //      scheme                 Activity
     String forceNewActivityKey() default ""; 
    }
    앞에서 열거 한 여러 가지 수 요 는 모두 SchemeHandler 와 두 개의 scheme 에서 나타 난 것 을 알 수 있다.
    쓰다
    업무 사용자 에 대해 우 리 는Activity또는Fragment에 주 해 를 붙 여야 한다.QMUISchemeHandler기본 값 은 인 자 를 분석 하여Activityintent 나Fragment의 arguments 에 넣 습 니 다.따라서 우 리 는onCreate에서 우리 가 관심 을 가 지 는 값 을 꺼 낼 수 있 습 니 다.
    
    @ActivityScheme(name="activity1")
    class Activity1: QMUIActivity{
    
     override fun onCreate(...){
     ...
     if(isStartedByScheme()){
      //    intent extra       
      val param1 = getIntent().getStringExtra(paramName)
     }
     }
    }
    
    @FragmentScheme(name="activity1", activities = {QDMainActivity.class})
    class Fragment1: QMUIFragment{ 
     override fun onCreate(...){
     ...
     if(isStartedByScheme()){
      //    arguments       
      val param1 = getArguments().getString(paramName)
     }
     }
    }
    이러한 전송 방법 은 안 드 로 이 드 공식 디자인 의 방법 에 매우 부합 되 는데 이것 도Fragment무 참 구조 기의 사용 방식 을 따라 야 한다.
    WebView 에 대해 서 는 재 작성WebViewClient#shouldOverrideUrlLoading을 통 해 scheme 점프 를 처리 할 수 있 습 니 다.
    
    class MyWebViewClient: WebViewClient{ 
     override fun shouldOverrideUrlLoading(view: WebView, url: String){
      if(schemeHandler.handle(url)){
       return true;
      }
      return super.shouldOverrideUrlLoading(view, url);
     }
    
     override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest){
      if(schemeHandler.handle(request.getUrl().toString())){
       return true;
      }
      return super.shouldOverrideUrlLoading(view, request);
     }
    }
    이루어지다QMUISchemeHandler코드 생 성 방식 으로 컴 파일 기간 에 하나의SchemeMapImpl류 를 생 성하 여SchemeMap류 를 실현 했다.
    
    public interface SchemeMap {
    
     //    action       SchemeItem
     SchemeItem findScheme(QMUISchemeHandler handler, String schemeAction, Map<String, String> params);
     //    schemeAction     
     boolean exists(QMUISchemeHandler handler, String schemeAction);
    }
    각 scheme 의 주 해 는 하나SchemeItem에 대응 합 니 다.
  • ActivityScheme대응 실례 화 1 개ActivitySchemeItem류 를 맵 에 추가
  • FragmentScheme대응 실례 화 1 개FragmentSchemeItem류 를 맵 에 추가
  • 컴 파일 기간SchemeProcessor을 통 해 생 성 된SchemeMapImpl은 대략 다음 과 같다.
    
    public class SchemeMapImpl implements SchemeMap { 
     private Map<String, List<SchemeItem>> mSchemeMap;
    
     public SchemeMapImpl() {
     mSchemeMap = new HashMap<>();
     List<SchemeItem> elements;
     ArrayMap<String, String> required = null;
     elements = new ArrayList<>();
     required =null;
     elements.add(new FragmentSchemeItem(QDSliderFragment.class,false,new Class[]{QDMainActivity.class},null,false,"",required,null,null,null,null,null,SliderSchemeMatcher.class));
     mSchemeMap.put("slider", elements);
    
     elements = new ArrayList<>();
     required = new ArrayMap<>();
     required.put("aa", null);
     required.put("bb", "3");
     elements.add(new ActivitySchemeItem(ArchTestActivity.class,true,null,required,null,new String[]{"aa"},null,null,null,null));
     mSchemeMap.put("arch", elements);
    
     }
    
     @Override
     public SchemeItem findScheme(QMUISchemeHandler arg0, String arg1, Map<String, String> arg2) {
     List<SchemeItem> list = mSchemeMap.get(arg1);
     if(list == null || list.isEmpty()) {
      return null;
     }
     for (int i = 0; i < list.size(); i++) {
      SchemeItem item = list.get(i);
      if(item.match(arg0, arg2)) {
      return item;
      }
     }
     return null;
     }
    
     @Override
     public boolean exists(QMUISchemeHandler arg0, String arg1) {
     return mSchemeMap.containsKey(arg1);
     }
    }
    전체적인 디자인 과 실현 방향 은 바로 이렇다.나머지 는 각종 인 코딩 디 테 일이 다.관심 있 는 것 은QMUISchemeHandler#handle()을 통 해 추적 하거나SchemeProcessor코드 생 성 을 어떻게 하 는 지 볼 수 있다.이 기능 은 보기 에는 간단 해 보이 지만 사실은 Builder 모델,책임 체인 모델,공장 방법 등 디자인 모델 의 운용 도 포함 하고 SchemeMatcher,SchemeItem 등 대상 을 대상 으로 하 는 인터페이스,계승,다 형 등에 대한 운용 도 포함한다.읽 어 보 세 요.당신 에 게 깨 우 침 이 있 을 지도 모 릅 니 다.당신 도 잠재 적 인 bug 를 발견 할 수 있 을 지도 모 릅 니 다.
    총결산
    안 드 로 이 드 scheme 점프 의 디자인 과 실현 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 안 드 로 이 드 scheme 점프 의 디자인 과 실현 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 바 랍 니 다!

    좋은 웹페이지 즐겨찾기