Android开发 在子线程进行登录操作

注意:
  在android开发中,主线程不能进行耗时操作,所以我们经常把耗时操作放在子线程中进行,那么就需要子线程与主线程相互交流,就需要使用到handler. 而在使用handler过程中,如果对handler使用不太熟练的话就偶尔会出现
Can
't create handler inside thread that has not called Looper.prepare()的报错异常。
之前在Handler的原理的博文中有讲到,Handler的使用会依靠Looper循环来发送消息,如果不创建Looper对象,消息就无法发送,系统就会崩溃。
那么为什么使用handler有时候可以运行,有时候不能运行呢?
    其实就是如果在主线程中创建handler时,系统会自动创建Looper,但是在子线程中创建handler时,是不会自动创建Looper的,
此时如果不手动创建Looper,系统就会崩溃。

 

一、在LoginActivity点击登录按钮

public void onClick(View v) {
        switch (v.getId()){
            case R.id.login_btn: //登录
          //获取输入框信息 String name = lg_username.getText().toString().trim(); String password = lg_password.getText().toString().trim(); if (!TextUtils.isEmpty(name) && !TextUtils.isEmpty(password)) { UserBean userBean = new UserBean(); userBean.setUserName(name); userBean.setUserPassword(password); userBean.setBalance(0.0);          //在这开启子线程 } }

二、在onClick()方法中开启子线程

 //显示正在登录
                    dialog.showProgressDialog(LoginActivity.this,"提示","正在登录...");
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                String result = new DealData().getDateFromSever(Constance.LOGIN,userBean);
                                UserBean resultUser = JSON.parseObject(result,UserBean.class);
                                Message msg = new Message();
                                Bundle bundle = new Bundle();
                                bundle.putSerializable("curUser",resultUser);
                                bundle.putString("password",password);
                                msg.setData(bundle);
                                msg.what = 1;
                                handler.sendMessage(msg);
                            }catch (Exception e){
                                e.printStackTrace();
                            }
                        }
                    }).start();

                } else {
                    Toast.makeText(this, "请输入你的用户名或密码!", Toast.LENGTH_SHORT).show();
                }
                break;
}

 

三、主线程的handler处理消息

//主线程中接收子线程发送的消息并处理
    private Handler handler=new Handler(){
        @SuppressLint("HandlerLeak")
        public void handleMessage(Message msg){
            try {
                switch (msg.what){
                    case 1:
                        UserBean resultUser = (UserBean) msg.getData().getSerializable("curUser");
                        String password = msg.getData().getString("password");
                        if(resultUser!=null&&resultUser.getUserName()!=null){
                            dialog.hideProgressDialog();
                            //判断
                            if (password.equals(resultUser.getUserPassword())){
                                new ShowMassage().showMsg("登录成功!",LoginActivity.this);
                                Intent intent1 = new Intent(LoginActivity.this,MainActivity.class);
                                Bundle bundle = new Bundle();
                                bundle.putSerializable("curUser",resultUser);
                                intent1.putExtras(bundle);
                                startActivity(intent1);
                                finish();//销毁此Activity
                            }else{
                                new ShowMassage().showMsg("用户名或密码错误!",LoginActivity.this);
                            }
                        }else{
                            dialog.hideProgressDialog();
                            new ShowMassage().showMsg("您未注册!",LoginActivity.this);
                        }

                    default:
                        Log.e("400", " handler fail in send" );
                }

            }catch (Exception e){
                e.printStackTrace();
            }
        }
    };

四、所有代码

activity_login.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:background="@drawable/app_bg">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="100dp"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="20dp">

        <!--圆形图片-->
        <com.google.android.material.imageview.ShapeableImageView
            android:id="@+id/login_avatar"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_centerHorizontal="true"
            android:src="@drawable/logo"
            app:shapeAppearanceOverlay="@style/circleImageStyle" />

        <EditText
            android:id="@+id/lg_username"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:layout_below="@id/login_avatar"
            android:layout_alignParentEnd="true"
            android:layout_marginTop="27dp"
            android:layout_marginEnd="0dp"
            android:drawablePadding="5dp"
            android:hint="用户名"
            android:maxLines="1" />

        <EditText
            android:id="@+id/lg_password"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:layout_below="@id/lg_username"
            android:drawablePadding="5dp"
            android:hint="密码"
            android:inputType="textPassword"
            android:maxLines="1" />

        <LinearLayout
            android:id="@+id/ly"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/lg_password"
            android:orientation="horizontal">

            <CheckBox
                android:id="@+id/lg_rememberPsd"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="5"
                android:text="记住密码"
                android:textColor="#1E90FF" />

            <TextView
                android:id="@+id/lg_forgetPsd"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="忘记密码"
                android:textColor="#1E90FF" />

        </LinearLayout>

        <Button
            android:id="@+id/login_btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/ly"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="30dp"
            android:background="@drawable/search_shape_btn_accent"
            android:text="登录"
            android:textColor="#FFFFFF"
            android:textSize="18sp" />


    </RelativeLayout>

    <TextView
        android:id="@+id/lg_register"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="9dp"
        android:layout_gravity="right"
        android:layout_marginRight="20dp"
        android:text="没有账号?立即注册"
        android:textColor="#1E90FF"/>

    <TextView
        android:id="@+id/lg_other"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="其他登录方式"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="150dp"
        android:layout_gravity="center_horizontal"/>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="15dp">

        <ImageView
            android:id="@+id/lg_qq"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:src="@drawable/qq"
            android:layout_marginRight="15dp"/>

        <ImageView
            android:id="@+id/lg_wechat"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:src="@drawable/wechat"/>
    </LinearLayout>

</LinearLayout>

LoginActivity.java

package com.example.campus.app;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
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.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;


import com.alibaba.fastjson.JSON;
import com.example.campus.R;
import com.example.campus.bean.Result;
import com.example.campus.bean.UserBean;
import com.example.campus.utils.Constance;
import com.example.campus.utils.DealData;
import com.example.campus.utils.LoadingDataUtil;
import com.example.campus.utils.MainConstant;
import com.example.campus.utils.ShowMassage;
import com.google.android.material.imageview.ShapeableImageView;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;

/**
 * 此类 implements View.OnClickListener 之后,
 * 就可以把onClick事件写到onCreate()方法之外
 * 这样,onCreate()方法中的代码就不会显得很冗余
 */
public class LoginActivity extends AppCompatActivity implements View.OnClickListener {

    private ShapeableImageView lg_avatar;
    private EditText lg_username, lg_password;
    private TextView lg_forgetPsd;
    private TextView lg_register;
    private Button login_btn;
    private ImageView lg_qq;
    private ImageView lg_wechat;

    private LoadingDataUtil dialog = new LoadingDataUtil();

    //声明主线程的handler
    //主线程中接收子线程发送的消息并处理
    private Handler handler=new Handler(){
        @SuppressLint("HandlerLeak")
        public void handleMessage(Message msg){
            try {
                switch (msg.what){
                    case 1:
                        UserBean resultUser = (UserBean) msg.getData().getSerializable("curUser");
                        String password = msg.getData().getString("password");
                        if(resultUser!=null&&resultUser.getUserName()!=null){
                            dialog.hideProgressDialog();
                            //判断
                            if (password.equals(resultUser.getUserPassword())){
                                new ShowMassage().showMsg("登录成功!",LoginActivity.this);
                                Intent intent1 = new Intent(LoginActivity.this,MainActivity.class);
                                Bundle bundle = new Bundle();
                                bundle.putSerializable("curUser",resultUser);
                                intent1.putExtras(bundle);
                                startActivity(intent1);
                                finish();//销毁此Activity
                            }else{
                                new ShowMassage().showMsg("用户名或密码错误!",LoginActivity.this);
                            }
                        }else{
                            dialog.hideProgressDialog();
                            new ShowMassage().showMsg("您未注册!",LoginActivity.this);
                        }

                    default:
                        Log.e("400", " handler fail in send" );
                }

            }catch (Exception e){
                e.printStackTrace();
            }
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);//禁止横屏
        setContentView(R.layout.activity_login);

        initView();//初始化界面

    }

    private void initView() {
        //初始化控件
        lg_avatar = findViewById(R.id.login_avatar);
        lg_username = findViewById(R.id.lg_username);
        lg_password = findViewById(R.id.lg_password);
        lg_forgetPsd = findViewById(R.id.lg_forgetPsd);
        login_btn = findViewById(R.id.login_btn);
        lg_register = findViewById(R.id.lg_register);
        lg_qq = findViewById(R.id.lg_qq);
        lg_wechat = findViewById(R.id.lg_wechat);

        login_btn.setOnClickListener(this);
        lg_register.setOnClickListener(this);
        lg_forgetPsd.setOnClickListener(this);
        lg_qq.setOnClickListener(this);
        lg_wechat.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.lg_register: //注册
                Intent intent = new Intent(LoginActivity.this, RegisteredActivity.class);//跳转到注册界面
                startActivity(intent);
                finish();
                break;
            case R.id.lg_forgetPsd:
                Intent intent2 = new Intent(LoginActivity.this,PhoneLoginActivity.class);
                startActivity(intent2);
                break;
            case R.id.login_btn: //登录
                String name = lg_username.getText().toString().trim();
                String password = lg_password.getText().toString().trim();
                if (!TextUtils.isEmpty(name) && !TextUtils.isEmpty(password)) {
                    UserBean userBean = new UserBean();
                    userBean.setUserName(name);
                    userBean.setUserPassword(password);
                    userBean.setBalance(0.0);

                    //显示正在登录
                    dialog.showProgressDialog(LoginActivity.this,"提示","正在登录...");
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                String result = new DealData().getDateFromSever(Constance.LOGIN,userBean);
                                UserBean resultUser = JSON.parseObject(result,UserBean.class);
                                Message msg = new Message();
                                Bundle bundle = new Bundle();
                                bundle.putSerializable("curUser",resultUser);
                                bundle.putString("password",password);
                                msg.setData(bundle);
                                msg.what = 1;
                                handler.sendMessage(msg);
                            }catch (Exception e){
                                e.printStackTrace();
                            }
                        }
                    }).start();
                } else {
                    Toast.makeText(this, "请输入你的用户名或密码!", Toast.LENGTH_SHORT).show();
                }
                break;
        }
    }
}

ShowMassage.java

package com.example.campus.utils;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.view.Gravity;
import android.widget.Toast;

import com.example.campus.app.RegisteredActivity;

public class ShowMassage {
    public void showMsg(String msg, Context mContext) {
        Handler handler = new Handler(Looper.getMainLooper());
        handler.post(new Runnable() {
            @Override
            public void run() {
                //放在UI线程弹Toast
                Toast toast = Toast.makeText(mContext,msg,Toast.LENGTH_LONG);
                toast.setGravity(Gravity.CENTER,0,0);
                toast.show();
            }
        });
    }
}

DealData.java  

 //进行http请求并获取返回的数据
    public String getDateFromSever(String url, UserBean userBean) {
        try {
            OkHttpClient client = new OkHttpClient();
            RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),
                    JSON.toJSON(userBean).toString());
            Request request = new Request.Builder()
                    .url(url)
                    .addHeader("key","value")
                    .post(requestBody)
                    .build();
            Response response = client.newCall(request).execute();
            Log.d("100", "Ipaws response="+response);
            String responseData = response.body().string();
            if (response.isSuccessful()) {
                return responseData;
            }else {
                Log.d("400", "responseData: error");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

 

posted @ 2023-03-01 22:31  湘summer  阅读(56)  评论(0编辑  收藏  举报