CC框架实践(1):实现登录成功再进入目标界面功能

前言

在掘金上看到这篇文章:android 关于先登录成功后再进入目标界面的思考,作者对实现登录成功后再跳转到目标界面功能作了比较详细的分析,对比了一些已有的实现方案并指出存在的问题。最终,作者实现了一个可同时添加多个条件判断拦截的方案,思路很新颖。

这篇文章的阅读量和收藏数都很多,看来大家对这个需求的关注度很高,这里将我们在使用 CC框架 过程中实现这个功能的方案跟大家分享一下。

先简单介绍一下CC框架

CC: Component Caller(github地址),是一个可跨app进行组件调用的android组件化开发框架,可支持包括Activity跳转、数据获取、网络请求等等几乎所有指令的跨组件调用。

组件实现方可自行决定是同步实现还是异步实现。

调用方可自行决定是同步调用还是异步调用(<font color=red>Notice: 不要在主线程同步调用耗时操作</font>)。

并且组件调用可关联Activity和Fragment的生命周期(在onDestroy被调用时自动取消调用,避免出现内存泄露)

CC框架的使用方式,可查看github中的 README文档

CC框架的实现原理 详细介绍

CC框架基因中自带支持组件层面的AOP

在定义组件时,实现IComponent.onCall(cc)方法,并根据cc中的参数来执行组件中的具体逻辑(如:页面跳转等)。

可以在调用具体逻辑之前对该功能进行AOP实现,例如:登录、页面数据预加载等

用CC框架实现必须先登录再进入目标页面功能

目标页面所在的组件在执行页面跳转前调用登录组件(用户中心组件)获取用户信息,若未登录则登录后返回用户信息。

这里有2个点:
1. 若用户已登录,则直接返回用户信息,同步方式实现即可
2. 若用户未登录,则跳转到登录页面,需要执行完登录操作(或取消)后才能获得结果,使用异步方式实现。

以打开订单列表页面前需要登录为例:

  1. 先定义用户组件,提供一个强制获取用户登录信息的功能,若未登录则打开登录界面,并在用户登录后返回登录结果(取消登录也是一种结果)
//用户中心组件类
public class UserComponent implements IComponent {
    @Override
    public String getName() {
        return "demo.component.user";
    }

    @Override
    public boolean onCall(CC cc) {
        String actionName = cc.getActionName();
        // ... 
        // 强制获取用户信息,若未登录则跳转到登录,并将登录结果返回
        if ("forceGetLoginUser".equals(actionName)) {
            if (!TextUtils.isEmpty(Global.loginUserName)) {
                //已登录同步实现,直接调用CC.sendCCResult(...)并返回返回false
                CCResult result = CCResult.success(Global.KEY_USERNAME, Global.loginUserName);
                CC.sendCCResult(cc.getCallId(), result);
                return false;
            }
            //未登录,打开登录界面,在登录完成后再回调结果,异步实现
            Context context = cc.getContext();
            Intent intent = new Intent(context, LoginActivity.class);
            if (!(context instanceof Activity)) {
                //调用方没有设置context或app间组件跳转,context为application
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            }
            //将cc的callId传给Activity,登录完成后通过这个callId来回传结果
            intent.putExtra("callId", cc.getCallId());
            context.startActivity(intent);
            //异步实现,不立即调用CC.sendCCResult,返回true
            return true;
        }
        //...
        return false;
    }

}
  1. 模拟的登录页面:点击按钮模拟登录,直接返回文本框中的信息作为登录成功的信息,若未登录直接返回,则视为取消登录
/**
 * 模拟登录页面
 */
public class LoginActivity extends AppCompatActivity implements View.OnClickListener {

    private EditText editText;
    private String callId;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.id.activity_login);
        callId = intent.getStringExtra("callId");
        //init views
    }

    @Override
    public void onClick(View v) {
        //模拟登录:点击按钮获取文本框内容并作为用户登录信息返回
        String username = editText.getText().toString().trim();
        if (TextUtils.isEmpty(username)) {
            Toast.makeText(this, R.string.demo_b_username_hint, Toast.LENGTH_SHORT).show();
        } else {
            //登录成功,返回
            Global.loginUserName = username;
            finish();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //判断是否为CC调用打开本页面
        if (callId != null) {
            CCResult result;
            if (TextUtils.isEmpty(Global.loginUserName)) {
                result = CCResult.error("login canceled");
            } else {
                result = CCResult.success(Global.KEY_USERNAME, Global.loginUserName);
            }
            //为确保不管登录成功与否都会调用CC.sendCCResult,在onDestroy方法中调用
            CC.sendCCResult(callId, result);
        }
    }
}
  1. 在订单组件中进行登录验证:登录成功,则跳转到订单列表页;登录失败,则返回调用失败的结果
//订单组件
public class OrderComponent implements IComponent {
    @Override
    public String getName() {
        return "demo.component.order";
    }

    @Override
    public boolean onCall(CC cc) {
        CCResult result = CC.obtainBuilder("demo.component.user")
                .setActionName("forceGetLoginUser")
                .build()
                .call();
        CCResult ccResult;
        // 根据登录状态决定是否打开页面
        // 这里也可以添加更多的前置判断逻辑
        if (result.isSuccess()) {
            ccResult = CCResult.success();
            //登录成功,打开目标页面
            startOrderListActivity(cc);
        } else {
            //登录失败,返回失败信息
            ccResult = result;
        }
        //调用方不需要获得额外的信息,只需要知道调用状态
        //所以这个组件采用同步实现:同步调用CC.sendCCResult(...) 并且返回false
        CC.sendCCResult(cc.getCallId(), ccResult);
        return false;
    }

    private void startOrderListActivity(CC cc) {
        Context context = cc.getContext();
        Intent intent = new Intent(context, OrderListActivity.class);
        if (!(context instanceof Activity)) {
            // context maybe an application object if caller dose not setContext
            // or call across apps
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        }
        context.startActivity(intent);
    }
}

至此,打开订单页面必须登录的功能已全部完成。

这样实现的好处

  1. 登录组件只管登录自身的逻辑,跟其它逻辑完全不耦合
  2. 调用订单组件的地方无需添加额外的代码
  3. 可以添加任意的前置条件判断
  4. 登录条件的判断可用于任意组件而无需修改登录组件的逻辑
  5. 支持跨app组件调用时的前置条件判断

了解更多关于CC框架的信息

Github源码 ,持续维护更新中, 欢迎watch、fork、star、pr、提issue

系列文章

CC框架实践(1):实现登录成功再进入目标界面功能

CC框架实践(2):Fragment和View的组件化

CC框架实践(3):让jsBridge更优雅

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,319评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,801评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,567评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,156评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,019评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,090评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,500评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,192评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,474评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,566评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,338评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,212评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,572评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,890评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,169评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,478评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,661评论 2 335

推荐阅读更多精彩内容