任务 6.2 云笔记 - 用户认证(5)

六、编写用户数据获取模块

通常应用程序应当提供用户个人信息和配置模块以浏览、编辑个人配置,或者退出登录状态。
我们编写一个简单的个人信息模块,能够根据当前登录的用户账号从服务器端查询用户信息并显示,并且提供注销操作。具体设计如下:

  • 前置条件:用户已登录
  • 用户点击笔记列表页面ActionBar上的用户图标,进入用户信息页面
  • 用户信息页面展示用户email地址和个人签名
  • 用户信息页面提供登出按钮
  • 用户点击登出按钮后,APP清除登录数据,同时切换到登录页面

编写服务端查询页面

回到DreamWeaver(以下简称DW),创建新页面,命名为user_info.php,仍然保存到simple_note目录下。页面代码如下:

<?
session_start();
include( "conn.php" );
$email = $_POST[ "email" ];

// 在数据库中查询与email和密码完全匹配的记录
$sql = "SELECT * FROM `user` WHERE `email`='$email'";
$result = mysql_query( $sql );
$num_rows = mysql_num_rows( $result );
// 将用JSON返回登录结果
header( 'Content-type: text/json' );

if ( $num_rows == 1 ) {
    // 查询成功
    $row = mysql_fetch_array( $result );
    // 生成含有结果信息的JSON    
    $ret = array(
        "code" => "1",
        "msg" => "OK",
        "email" => $row[ 'email' ],
        "personalSign" => $row[ 'sign' ]
    );
    echo json_encode( $ret, JSON_UNESCAPED_UNICODE );
} else {
        // 不存在对应用户信息,返回出错信息
    $ret = array(
        "code" => "0",
        "msg" => "No such a user",
        "email" => $row[ 'email' ]
    );
    echo json_encode( $ret, JSON_UNESCAPED_UNICODE );
}

?>

创建用户信息页面

新建名为UserInfoActivity的新页面:

配置其对应的布局文件activity_user_info.xml如下:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".UserInfoActivity">

    <!--登出按钮-->
    <Button
        android:id="@+id/btn_logout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginStart="16dp"
        android:text="登出账户"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <!--Email信息-->
    <TextView
        android:id="@+id/tv_email"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="100dp"
        android:text="a@abc.com"
        android:textColor="@color/black"
        android:textSize="24sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <!--个人签名-->
    <TextView
        android:id="@+id/tv_personal_sign"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="24dp"
        android:text="Personal sign"
        android:textSize="18sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tv_email" />

    <!--加载等待动画-->
    <ProgressBar
        android:id="@+id/load_progress"
        style="?android:attr/progressBarStyleLarge"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

回到UserInfoActivity类中,为其添加成员变量如下:

    // 等待动画
    private ProgressBar mProgressBar;
    // Email文本
    private TextView mEmailView;
    // 个人签名文本
    private TextView mPersonalSignView;
    // 登出按钮
    private Button mLogoutView;

    private Handler mHandler = new Handler();

修改onCreate()方法:

        mProgressBar = findViewById(R.id.load_progress);
        mEmailView = findViewById(R.id.tv_email);
        mPersonalSignView = findViewById(R.id.tv_personal_sign);
        mLogoutView = findViewById(R.id.btn_logout);
        // 执行登出
        mLogoutView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onLogout();
            }
        });
        // 从服务器加载用户信息
        loadUserInfo();

基于okhttp3框架实现loadUserInfo()函数:

    private void loadUserInfo() {
        String email = Utils.getUserEmail(this);
        // 当前并没有登录,跳转到登录页面
        if (TextUtils.isEmpty(email)) {
            Intent intent = new Intent(this, LoginActivity.class);
            startActivity(intent);
            finish();
            return;
        }

        OkHttpClient client = new OkHttpClient();
        FormBody.Builder fb = new FormBody.Builder();
        FormBody formBody = fb.add("email", email)
                .build();
        Request request = new Request.Builder()
                .url(HttpHelper.getUserInfoUrl())
                .post(formBody)
                .build();

        showProgress(true);

        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        showProgress(false);
                        Toast.makeText(UserInfoActivity.this, R.string.error_check_network, Toast.LENGTH_SHORT).show();
                    }
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                ...
            }
        });
    }

在onResponse()回调函数中编写下面的代码:

                final String rsp = response.body().string();
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        showProgress(false);
                        try {
                            JSONObject jo = new JSONObject(rsp);
                            int code = jo.optInt("code", 0);
                            String email = jo.optString("email");
                            String personalSign = jo.optString("personalSign");
                            if (code == 1) {
                                // 查询成功,设置当前要显示的各个字段
                                mEmailView.setText(email);
                                mPersonalSignView.setText(personalSign);
                            } else {
                                // 查询失败,关闭页面退出
                                finish();
                                return;
                            }
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                });

下面实现登出功能,这里简单的处理,就是将之前登录后保存的账户设置为空即可:

    private void onLogout() {
        Utils.saveUserEmail(this, "");
        finish();
    }

还要实现控制等待动画显示与隐藏的showProgress()函数:

    private void showProgress(final boolean show) {
        mProgressBar.setVisibility(show ? View.VISIBLE : View.GONE);
    }

为笔记列表页ActionBar添加用户信息项

将以下图标文件放置到res/drawable-xxhdpi目录中:

ic_person.png

进入到笔记列表页对应的菜单资源文件menu_note_list.xml中,增加菜单项menu_item_user如下:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/menu_item_notebook"
        android:title="@string/notebook"
        android:icon="@drawable/ic_notebook"
        app:showAsAction="always"/>

    <!--新增用户信息项-->
    <item
        android:id="@+id/menu_item_user"
        android:title="@string/user_info"
        android:icon="@drawable/ic_person"
        app:showAsAction="always"/>
</menu>

需要新增的字符串:

    <string name="user_info">用户信息</string>

回到笔记列表页,找到onOptionsItemSelected()方法,为其添加代码,在点击用户信息图标时打开用户信息页面:

            case R.id.menu_item_user:
                intent = new Intent(this, UserInfoActivity.class);
                startActivity(intent);
                return true;

运行程序,效果如下:

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,039评论 25 707
  • 五、编写客户端注册/登录模块 前面我们创建了简单的服务端用户身份认证服务。现在我们回到客户端,编写对应的注册/登录...
    jingz课程阅读 524评论 0 0
  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 6,389评论 0 17
  • 说起坏习惯,你会想到什么? 拖延症。拖延症就像是在时间沙漏旁埋了一个大大的时间黑洞,而这个时间黑洞就在你无所察觉的...
    柳闻文阅读 289评论 2 1
  • 记得王朔在小说《过把瘾就死》中把恋爱里疼入心肺、难得见光的一面写到剥肉拆骨,小说中那对未受任何外界阻挠的男女在不断...
    英以阅读 589评论 0 3