IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android studio|登录页面设计——okhttp登录并返回用户头像 -> 正文阅读

[移动开发]Android studio|登录页面设计——okhttp登录并返回用户头像

按照老师的要求做了个简陋的登录界面,实现用户登录并获取头像的功能。因为本人完全是个小白,做下来踩了不少坑,这里记录一下,之后遇到类似情况方便处理。

这里只实现了安卓的部分,服务器的东西没有涉及。

参考的部分文章:

《第一行代码》

https://blog.csdn.net/hxy19971101/article/details/76177408?locationNum=3&fps=1

https://blog.csdn.net/kuankuan199308153614/article/details/103260721

先展示一下成品:首先是基本的登录界面,有账号和密码两个输入框和一个登录按钮,初始头像显示灰色,其他的组件没有派上什么用场。在没有输入用户名或者密码的情况下、输入的用户名或密码不正确的情况下弹窗提示。如果输入正确的用户名和头像,显示登录成功,并返回用户的头像:

?

?

?

?

?

?

?

?

?布局主要使用相对布局。目前我认为相对布局的重点就是给每个组件命名,放新组件的时候写清楚新组件在之前哪个组件的上下左右就好了。第一次写,命名有点乱七八糟,之后会慢慢改规范。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    android:orientation="vertical"
    android:background="@drawable/login_background"
    tools:context=".LoginActivity">

    <ImageView
        android:id="@+id/login_logo"
        android:layout_width="match_parent"
        android:layout_height="250dp"
        android:layout_marginTop="50dp"
        android:gravity="center_horizontal"
        android:src="@drawable/login_logo"/>

    <ImageView
        android:id="@+id/login_ima"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_below="@id/login_logo"
        android:layout_marginTop="30dp"
        android:layout_centerHorizontal="true"
        android:src="@drawable/login_old_ima"/>

    <EditText
        android:id="@+id/login_account"
        android:layout_width="260dp"
        android:layout_height="30dp"
        android:layout_below="@id/login_ima"
        android:layout_marginTop="30dp"
        android:layout_centerHorizontal="true"
        android:background="@color/white"
        android:hint=" 账号"
        android:textColorHint="#A4A4A4"
        android:textSize="16sp"
        android:paddingLeft="5dp"
        android:textColor="#2E2E2E"/>
    <EditText
        android:id="@+id/login_password"
        android:layout_width="260dp"
        android:layout_height="30dp"
        android:layout_below="@id/login_account"
        android:layout_marginTop="20dp"
        android:layout_centerHorizontal="true"
        android:background="@color/white"
        android:inputType="textPassword"
        android:hint=" 密码"
        android:textColorHint="#A4A4A4"
        android:textSize="16sp"
        android:paddingLeft="5dp"
        android:textColor="#2E2E2E"/>

    <CheckBox
        android:id="@+id/login_rempwd"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/login_password"
        android:layout_marginTop="20dp"
        android:layout_alignLeft="@id/login_account"
        android:text="记住密码"
        android:textColor="@color/white"
        android:textSize="15sp"/>
    <CheckBox
        android:id="@+id/login_offline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/login_password"
        android:layout_marginTop="20dp"
        android:layout_alignRight="@id/login_account"
        android:layout_marginRight="10dp"
        android:text="离线模式"
        android:textColor="@color/white"
        android:textSize="15sp"/>

    <Button
        android:id="@+id/login_loginbutton"
        android:layout_width="260dp"
        android:layout_height="56dp"
        android:layout_below="@id/login_rempwd"
        android:layout_marginTop="20dp"
        android:layout_centerHorizontal="true"
        android:text="登 录"
        android:textSize="20sp"/>

</RelativeLayout>

?重要的还是逻辑部分。主要分几步去实现:①okhttp向服务器提交用户名和密码进行登录,并保存session;②通过获取用户头像的接口,用okhttp获取头像地址的后半部分url;③拼接url并访问,将返回的数据以图片形式显示出来。

在写的时候感觉一定要多用log把信息显示出来,包括从服务器那里获得的返回的数据,也都显示出来,方便进行调试。

在build.gradle(:app)文件里的dependencies下添加了okhttp的依赖,还有最后没用上的glide库的依赖。

implementation 'com.squareup.okhttp:okhttp:2.7.5'
implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.2'

implementation 'com.github.bumptech.glide:glide:4.12.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'

如果运行的时候glide库报了不能生成glidemodule的错误,可以在你新建别的java.class文件的地方新建一个java.class文件?,命名好像随便什么都行,写如下内容。我按这个做就没有报错了。

package com.example.mypractice;

import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.module.AppGlideModule;

@GlideModule
public class 你的命名 extends AppGlideModule {

}

?在AndroidManifest.xml文件里声明联网权限,写在<application前面:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.mypractice">

    <uses-permission android:name="android.permission.INTERNET" />  这一句联网

    <application
        android:allowBackup="true"  这一句隐藏标题栏
        android:icon="@mipmap/ic_launcher"

?准备工作就绪,开始实现登录功能。这里单独讲一些地方,然后直接贴代码好了:

①关于输入框里的字符串的获取:

需要先private EditText ed_account;,然后ed_account=findViewById(R.id.login_account);将

?java文件这边定义的东西和布局文件那边的联系起来,然后edi_account=ed_account.getText().toString().trim();获取字符串,trim是为了去除开始的空格。

②okhttp提交用户名和密码的表单:

//提交账号密码请求登录
RequestBody requestBody=new FormBody.Builder() //建立表单
        .add("account",edi_account)
        .add("password",edi_pwd)
        .build();
OkHttpClient client=new OkHttpClient(); 
Request request=new Request.Builder()
        .url("http://……/post")
        .post(requestBody)
        .build();
Response response=client.newCall(request).execute();
String responseData=response.body().string();
Log.d("输出结果:",responseData);

?③获取session,不然服务器不知道你是刚才登录的那个:

需要在第一次发请求的时候获取sessionid:

String session=response.headers().get("Set-Cookie");
String sessionid=session.substring(0,session.indexOf(";"));

?然后在之后发生请求的时候,都加上这个sessionid:

Request request1=new Request.Builder()
        .addHeader("cookie",sessionid)
        .url("http://……/post")
        .post(requestBody1)
        .build();

?④将获得的服务器的回应变成图像。这里本来是用glide加载的,但是一直报错,要我在主线程里面用glide。查了一下说最好不要在非主线程里面用glide,我也实在不知道怎么改才能不报错,就没有用glide了。

InputStream inputStream=response2.body().byteStream();
Bitmap bitmap= BitmapFactory.decodeStream(inputStream);
Message msg=new Message();
msg.obj=bitmap;
handler.sendMessage(msg);

不要忘了在上面重载一下handler:

private Handler handler=new Handler(){
    public void handleMessage(Message msg){
        Bitmap bitmap=(Bitmap)msg.obj;
        ge_ima.setImageBitmap(bitmap);
    }
};

?差不多就是这样了,有点写累了,贴一下完整的代码吧:

package com.example.mypractice;

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.bumptech.glide.Glide;

import java.io.InputStream;

import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class LoginActivity extends AppCompatActivity {

    private EditText ed_account,ed_pwd;
    private Button bu_login;
    private ImageView ge_ima;
    String edi_account,edi_pwd;
    private Handler handler=new Handler(){
        public void handleMessage(Message msg){
            Bitmap bitmap=(Bitmap)msg.obj;
            ge_ima.setImageBitmap(bitmap);
        }
    };

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

        ed_account=findViewById(R.id.login_account);
        ed_pwd=findViewById(R.id.login_password);
        bu_login=findViewById(R.id.login_loginbutton);
        ge_ima=findViewById(R.id.login_ima);


        bu_login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                edi_account=ed_account.getText().toString().trim();
                edi_pwd=ed_pwd.getText().toString().trim();
                if(TextUtils.isEmpty(edi_account) || TextUtils.isEmpty(edi_pwd))
                    Toast.makeText(LoginActivity.this,"请输入用户账号名或者密码",Toast.LENGTH_SHORT).show();
                else
                    login(edi_account,edi_pwd);
            }
        });
    }

    public void login(String edi_account,String edi_pwd){
        new Thread(new Runnable() {
            @Override
            public void run() {
                try{
                    Looper.prepare(); //为了在线程里使用Toast
                    Log.d("账号",edi_account);
                    Log.d("密码",edi_pwd);

                    //提交账号密码请求登录
                    RequestBody requestBody=new FormBody.Builder()
                            .add("account",edi_account)
                            .add("password",edi_pwd)
                            .build();
                    OkHttpClient client=new OkHttpClient();
                    Request request=new Request.Builder()
                            .url("http://……/post")
                            .post(requestBody)
                            .build();
                    Log.d("URL",request+"");
                    //获取回应并保存session
                    Response response=client.newCall(request).execute();
                    String responseData=response.body().string();
                    Log.d("输出结果:",responseData);
                    String session=response.headers().get("Set-Cookie");
                    String sessionid=session.substring(0,session.indexOf(";"));

                    if(!response.isSuccessful()){
                        Toast.makeText(LoginActivity.this,"用户名或密码错误",Toast.LENGTH_SHORT).show();
                    }
                    else{
                        Toast.makeText(LoginActivity.this,"用户"+responseData.substring(18,23)+"欢迎登录",Toast.LENGTH_SHORT).show();
                        //获取头像的url
                        RequestBody requestBody1=new FormBody.Builder()
                                .add("account",edi_account)
                                .build();
                        Request request1=new Request.Builder()
                                .addHeader("cookie",sessionid)
                                .url("http://……/post")
                                .post(requestBody1)
                                .build();
                        Response response1=client.newCall(request1).execute();
                        String responseData1=response1.body().string();
                        Log.d("输出结果:",responseData1);

                        if(!response1.isSuccessful()){
                            Toast.makeText(LoginActivity.this,"获取用户头像地址失败",Toast.LENGTH_SHORT).show();
                        }
                        else{
                            int len=responseData1.length();
                            String picUrl=responseData1.substring(51,len-4);//不会解析,暂时先这么写
                            Log.d("picUrl:",picUrl);

                            //拼接Url
                            String url1="http://……"+picUrl;
                            Log.d("picUrl:",url1);
                            //加载头像
                            Request request2=new Request.Builder()
                                    .addHeader("cookie",sessionid)
                                    .url(url1)
                                    .build();
                            Response response2=client.newCall(request2).execute();
                            InputStream inputStream=response2.body().byteStream();
                            Bitmap bitmap= BitmapFactory.decodeStream(inputStream);
                            Message msg=new Message();
                            msg.obj=bitmap;
                            handler.sendMessage(msg);
                            //Glide.with(getApplicationContext()).load(url1).into(ge_ima);
                        }
                    }
                    Looper.loop(); //和上面的looper是一对的
                }catch (Exception e){
                    e.printStackTrace();
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(LoginActivity.this,"网络连接失败!",Toast.LENGTH_SHORT).show();
                        }
                    });
                }
            }
        }).start();
    }
}

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-07-22 14:18:44  更:2021-07-22 14:19:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/2 7:55:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码