打開(kāi)頁(yè)面自動(dòng)登錄并回來(lái)-攔截器

并行的路.png

這篇文章的實(shí)現(xiàn)略有侵入性,但不妨礙你對(duì)這方面的思考宴猾,更好的實(shí)現(xiàn)可以參考另外一篇文章酌住。

在A(yíng)pp項(xiàng)目中有一些Activity是需要登錄成功后才能進(jìn)去的,比如訂單詳情頁(yè)刃麸,因?yàn)橛唵问歉~號(hào)掛鉤的醒叁,登錄的賬號(hào)一般會(huì)有個(gè)ID,需要帶著ID和訂單號(hào)去查訂單信息泊业。
很多剛開(kāi)始做App的同學(xué)會(huì)認(rèn)為應(yīng)該在進(jìn)入訂單詳情頁(yè)前先確保登錄成功把沼,也就是說(shuō)把登錄判斷和發(fā)起登錄都是進(jìn)入訂單詳情頁(yè)前搞定,的確這么做沒(méi)有問(wèn)題吁伺,但是恐怕體力活會(huì)很多吧饮睬,如果能理解攔截器的原理就可以簡(jiǎn)化我們的工作量。


@InterceptWith(LoginInterceptor.class)
public class OrderDetailActivity extends InterceptorActivity {
    private static final String EXTRA_ORDER_ID = "orderId";

    private TextView mOrderInfoText;
    private String mOrderId;

    public static void startActivity(Context context, String orderId) {
        Intent intent = new Intent(context, OrderDetailActivity.class);
        intent.putExtra(EXTRA_ORDER_ID, orderId);
        context.startActivity(intent);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_order_detail);

        mOrderId = getIntent().getStringExtra(EXTRA_ORDER_ID);
        mOrderInfoText = (TextView) findViewById(R.id.orderInfo);
    }

    @Override
    protected void invoked() {
        super.invoked();
        mOrderInfoText.setText("訂單信息(order id: " + mOrderId + ")");
        // 根據(jù)orderId請(qǐng)求完整的訂單信息
    }
}

看到以上訂單詳情頁(yè)只要在A(yíng)citvity class之上加上一個(gè)登錄校驗(yàn)的注解然后并在invoke()回調(diào)里執(zhí)行跟登錄相關(guān)的接口查詢(xún)及初始化頁(yè)面即可篮奄,這樣就不用關(guān)注登錄的實(shí)現(xiàn)細(xì)節(jié)捆愁,一定程度上解耦了你的業(yè)務(wù)實(shí)現(xiàn)割去。
下面我們說(shuō)說(shuō)實(shí)現(xiàn)方式,當(dāng)然這里的Interceptor并不是純粹利用Java的語(yǔ)言的動(dòng)態(tài)代理昼丑,這只是一種模仿呻逆,依附Activity的生命周期完成的:

  1. 定義Annotation:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface InterceptWith {

    /**
     * @return a Interceptor class array (must have a constructor without parameters inside)
     */
    Class<? extends Interceptor>[] value();
}

注:如果對(duì)Annotation不是很了解最好查閱下相關(guān)資料稍微了解下,這里就不過(guò)啰嗦了菩帝。

  1. 定義Interceptor父類(lèi)的基本的結(jié)構(gòu):
public abstract class Interceptor {

    /**
     * Request code used to start activity for result.
     *
     * @return request code
     */
    public abstract int getRequestCode();

    /**
     * Check interceptor's condition is meet or no.
     *
     * @param context Android context
     * @return condition is meet or no
     */
    public abstract boolean isSatisfied(Context context);

    /**
     * if condition was not satisfied, it'll be called to acquire resource or permission and so on.
     *
     * @param activity see {@link Activity}
     */
    public abstract void process(Activity activity);
}

注:以上是每個(gè)攔截器需要實(shí)現(xiàn)的抽象父類(lèi)咖城,以下以登錄校驗(yàn)的攔截器舉例:

public class LoginInterceptor extends Interceptor {

    @Override
    public int getRequestCode() {
        return LoginActivity.REQUEST_CODE_LOGIN;
    }

    @Override
    public boolean isSatisfied(Context context) {
        return UserConfigCache.isLogin(context);
    }

    @Override
    public void process(Activity activity) {
        LoginActivity.startActivityForResult(activity, getRequestCode());
    }
}
  1. 有攔截檢測(cè)功能的Activity:
public class InterceptorActivity extends AppCompatActivity {
    private List<Interceptor> mInterceptors = new ArrayList<>();

    /**
     * Called only when all interceptors verified OK,
     * so do your work here which all interceptors are passed.
     */
    protected void invoked() {
    }

    @Override
    protected void onStart() {
        super.onStart();
        if (mInterceptors.size() == 0) {
            scanInterceptors();
            verifyInterceptors();
        }
    }

    private void scanInterceptors() {
        mInterceptors.clear();

        InterceptWith annotation = getClass().getAnnotation(InterceptWith.class);
        if (annotation != null) {
            Class<? extends Interceptor>[] classes = annotation.value();
            for (Class<? extends Interceptor> clazz : classes) {
                try {
                    mInterceptors.add(clazz.newInstance());
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void verifyInterceptors() {
        if (mInterceptors.isEmpty()) {
            return;
        }

        for (int i = 0; i < mInterceptors.size(); i++) {
            Interceptor interceptor = mInterceptors.get(i);
            if (interceptor.isSatisfied(this)) {
                if (i == mInterceptors.size() - 1) {
                    invoked();
                    break;
                }
            } else {
                interceptor.process(this);
                break;
            }
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        for (Interceptor interceptor : mInterceptors) {
            if (interceptor.getRequestCode() == requestCode) {
                if (resultCode == RESULT_OK) {
                    verifyInterceptors();
                    break;
                } else if (resultCode == RESULT_CANCELED) {
                    finish();
                    break;
                }
            }
        }
    }
}

注:
主要通過(guò)在onStart()進(jìn)行對(duì)配置的攔截器進(jìn)行檢查,一旦有攔截器不滿(mǎn)足條件就跳轉(zhuǎn)對(duì)應(yīng)的頁(yè)面(如登錄頁(yè)面)請(qǐng)求資源胁附,當(dāng)資源請(qǐng)求獲取到后(登錄成功后)到了ActivityResult再校驗(yàn)其他攔截器酒繁,如果配置了多個(gè)攔截器則當(dāng)所有的攔截器都被滿(mǎn)足條件后會(huì)觸發(fā)invoked()回調(diào)函數(shù)執(zhí)行, 所以需要類(lèi)似登錄成功才能執(zhí)行的代碼就放在invoked()里好了。
當(dāng)然配置多個(gè)攔截器也很方便:

@InterceptWith({FirstInterceptor.class, SecondInterceptor.class, ThirdInterceptor.class})
public class XXXActivity extends InterceptorActivity
  1. 以上代碼除了LoginInterceptor.java是按業(yè)務(wù)定義的攔截器控妻,其余都可以作為common模塊里的代碼或者library中的代碼州袒,完整Demo源碼請(qǐng)參考Android Interceptor.
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市弓候,隨后出現(xiàn)的幾起案子郎哭,更是在濱河造成了極大的恐慌,老刑警劉巖夸研,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異姐扮,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)惊搏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)包雀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)才写,“玉大人赞草,你說(shuō)我怎么就攤上這事洲守」4迹” “怎么了叙谨?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵姑尺,是天一觀(guān)的道長(zhǎng)统捶。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么兑凿? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任圣絮,我火速辦了婚禮捧请,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘可款。我一直安慰自己埃叭,他們只是感情好误墓,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布欣范。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪狠半。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,007評(píng)論 1 284
  • 那天堂鲜,我揣著相機(jī)與錄音泡嘴,去河邊找鬼逆济。 笑死,一個(gè)胖子當(dāng)著我的面吹牛简僧,可吹牛的內(nèi)容都是我干的棉姐。 我是一名探鬼主播夏志,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼湿诊,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了瘦材?” 一聲冷哼從身側(cè)響起厅须,我...
    開(kāi)封第一講書(shū)人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎食棕,沒(méi)想到半個(gè)月后朗和,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡宣蠕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年例隆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抢蚀。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡镀层,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情唱逢,我是刑警寧澤吴侦,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站坞古,受9級(jí)特大地震影響备韧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜痪枫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一织堂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧奶陈,春花似錦易阳、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至徐勃,卻和暖如春事示,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背僻肖。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工肖爵, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人檐涝。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓遏匆,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親谁榜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子幅聘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)窃植,斷路器帝蒿,智...
    卡卡羅2017閱讀 134,599評(píng)論 18 139
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,504評(píng)論 25 707
  • ¥開(kāi)啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開(kāi)一個(gè)線(xiàn)程,因...
    小菜c閱讀 6,358評(píng)論 0 17
  • 開(kāi)發(fā)一款A(yù)pp巷怜,總會(huì)遇到各種各樣的需求和業(yè)務(wù)葛超,這時(shí)候選擇一個(gè)簡(jiǎn)單好用的輪子,就可以事半功倍 前言 上面一段代碼延塑,在...
    WangDeFa閱讀 65,701評(píng)論 44 199
  • I drank three glasses of wine the other day at lunch, the...
    by小微閱讀 168評(píng)論 5 2