原生登录注册和个人中心模块 Retrofit+OkHTTP+RxJava+Fresco

接口地址:

登录接口:

http://120.27.23.105/user/login

请求参数:

mobile 手机号  必填

password 密码 必填

 

注册接口:

http://120.27.23.105/user/reg

扫描二维码关注公众号,回复: 1518863 查看本文章

请求参数:

mobile 手机号 必填

password 密码  必填

 

个人中心接口:

http://120.27.23.105/user/getUserInfo

请求参数:

uid 用户id 必填

案例:实现原生登录注册和个人中心模块。(100分)

需求分析:

1. 新建一个工程,命名为UserCenter

2. 实现如图登录注册模块和个人中心模块,登录成功后跳转到个人中心页面;

3. 第二次进入自动登录;





  

效果图描述:

1. 使用RxJava结合Retrofit+OkHTTP封装工具类请求数据,使用MVP分层,进行原生登录,注册,个人信息页;

2. 使用Fresco加载图片,设置用户头像(图片上传或拍照)。

3. 实现如图登录注册模块和个人中心模块,登录成功后跳转到个人中心页面;

    第二次使用 SharedPreferences保存信息 进入自动登录;


首先在项目Model的build.gradle里面导入依赖

//butterknife在Studio3.0版本上需使用以下8.8.1版本(下面2行代码都要加)
compile 'com.jakewharton:butterknife:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'

compile 'com.facebook.fresco:fresco:1.5.0'

//由于Retrofit是基于OkHttp,所以还需要添加OkHttp库依赖
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-scalars:2.3.0'
compile 'com.squareup.okhttp3:okhttp:3.9.0'
//如果采用了 Gson 解析,需要在 Gradle加入retrofit2类库中的gson依赖
compile 'com.squareup.retrofit2:converter-gson:2.3.0'     //较新版本

compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.1.7'
compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'


新建MyApplication 继承Application ,并在清单文件中配置,添加网络权限

import android.app.Application;
import com.facebook.drawee.backends.pipeline.Fresco;

/**
 * 用于全局配置初始化异步加载类
 */
public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        //  用于全局配置初始化Fresco 图片加载
        Fresco.initialize(this);
    }
}
  1. <application  
  1.         
android :name= ".app.MyApplication"

  1. <uses-permission android:name="android.permission.INTERNET" />
    



请求网络获得的数据生成实体类(自己根据接口生成,这里不再重写)

1. 登录信息 LoginBean

用户登录信息 http://120.27.23.105/user/login?mobile=18631090582&password=888888

2. 注册信息 RegBean

用户注册数据  http://120.27.23.105/user/reg?mobile=18631090582&password=888888

3.个人信息  PersonInfoBean

个人信息数据  http://120.27.23.105/user/getUserInfo?uid=100


新建网络请求接口类GetDataInterface

import io.reactivex.Observable;
import retrofit2.http.FieldMap;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Query;

/**
 * 网络接口数据的请求类
 */
public interface GetDataInterface {

    //注册的接口
    //https://www.zhaoapi.cn/user/reg?mobile=18631090582&password=888888
    @FormUrlEncoded
    @POST("/user/reg")
    Observable<RegBean> reg(@FieldMap Map<String,String> map);

    //登录的接口
    //https://www.zhaoapi.cn/user/login?mobile=18631090582&password=888888
      @FormUrlEncoded
    @POST("/user/login")
    Observable<LoginBean> login(@FieldMap Map<String,String> map);

    //个人中心接口:
    //https://www.zhaoapi.cn/user/getUserInfo?uid=100
    @GET("/user/getUserInfo")
    Observable<PersonInfoBean> person(@Query("uid") int uid);
}


自定义 Retrofit+RxJava+OkHttp封装类请求接口数据

import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Retrofit+Rxjava+OkHttp 单例模式+双重锁模式 封装类
 */
public class RetrofitUnitl {
    private Retrofit mRetrofit;
    private String baseUrl;
    OkHttpClient client;
    private static RetrofitUnitl mRetrofitManager;
    private RetrofitUnitl(String baseUrl,OkHttpClient client){
        this.baseUrl=baseUrl;
        this.client=client;
        initRetrofit();
    }

    //单例模式+双重锁模式 封装方法
    public static synchronized RetrofitUnitl getInstance(String baseUrl,OkHttpClient client){
        if (mRetrofitManager == null){
            mRetrofitManager = new RetrofitUnitl(baseUrl,client);
        }
        return mRetrofitManager;
    }

    //实例化Retrofit请求
    private void initRetrofit() {
        mRetrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(client)
                .build();
    }

    //封装泛型方法
    public <T> T setCreate(Class<T> reqServer) {
        return mRetrofit.create(reqServer);
    }
}

自定义添加公共请求参数的拦截器

import java.io.IOException;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;

//自定义添加公共请求参数的拦截器
public class LoggingInterceptor implements Interceptor {
  @Override public Response intercept(Chain chain) throws IOException {
    Request request = chain.request();

    //开始响应的时间
    long t1 = System.nanoTime();
    //执行请求,返回响应的数据
    Response response = chain.proceed(request);
    //请求结束,响应返回
    long t2 = System.nanoTime();

    //响应的耗费时间
    System.out.println(" this request  url  " + response.request().url() + "  "  + (t2 - t1)/1000000);

    return response;
  }
}

自定义存取数据的SharedUtils

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;

public class SharedUtils {
   static SharedPreferences preferences;
   static String  File = "data";
   
   //保存数据的方法
   public static void savaBooleanData(Context context, String key,boolean value){
      if (preferences == null) {
         preferences = context.getSharedPreferences(File, Context.MODE_PRIVATE);
      }
      
      //获取编辑器对象
      Editor editor = preferences.edit();
      editor.putBoolean(key, value).commit();
   }
   
   //获取数据的方法
   public static boolean getBooleanData(Context context, String key,boolean defValue){
      if (preferences == null) {
         preferences = context.getSharedPreferences(File, Context.MODE_PRIVATE);
      }
      
      return preferences.getBoolean(key, defValue);
   }
}

自定义图片的上传及转换类  

import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * 图片的上传及转换类
 */
public class ImageUtils {
    /**
     * Save image to the SD card
     *
     * @param photoBitmap
     * @param photoName
     * @param path
     */
    public static String savePhoto(Bitmap photoBitmap, String path,
                                   String photoName) {
        String localPath = null;
        if (android.os.Environment.getExternalStorageState().equals(
                android.os.Environment.MEDIA_MOUNTED)) {
            File dir = new File(path);
            if (!dir.exists()) {
                dir.mkdirs();
            }

            File photoFile = new File(path, photoName + ".png");
            FileOutputStream fileOutputStream = null;
            try {
                fileOutputStream = new FileOutputStream(photoFile);
                if (photoBitmap != null) {
                    if (photoBitmap.compress(Bitmap.CompressFormat.PNG, 100,
                            fileOutputStream)) { // 转换完成
                        localPath = photoFile.getPath();
                        fileOutputStream.flush();
                    }
                }
            } catch (FileNotFoundException e) {
                photoFile.delete();
                localPath = null;
                e.printStackTrace();
            } catch (IOException e) {
                photoFile.delete();
                localPath = null;
                e.printStackTrace();
            } finally {
                try {
                    if (fileOutputStream != null) {
                        fileOutputStream.close();
                        fileOutputStream = null;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return localPath;
    }

    /**
     * 转换图片成圆形
     *
     * @param bitmap 传入Bitmap对象
     * @return
     */
    public static Bitmap toRoundBitmap(Bitmap bitmap) {
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        float roundPx;
        float left,top,right,bottom,dst_left,dst_top,dst_right,dst_bottom;
        if (width <= height) {
            roundPx = width / 2;
            top = 0;
            bottom = width;
            left = 0;
            right = width;
            height = width;
            dst_left = 0;
            dst_top = 0;
            dst_right = width;
            dst_bottom = width;
        } else {
            roundPx = height / 2;
            float clip = (width - height) / 2;
            left = clip;
            right = width - clip;
            top = 0;
            bottom = height;
            width = height;
            dst_left = 0;
            dst_top = 0;
            dst_right = height;
            dst_bottom = height;
        }
        Bitmap output = Bitmap.createBitmap(width,
                height, Config.ARGB_8888);
        Canvas canvas = new Canvas(output);
        final int color = 0xff424242;
        final Paint paint = new Paint();
        final Rect src = new Rect((int)left, (int)top, (int)right, (int)bottom);
        final Rect dst = new Rect((int)dst_left, (int)dst_top, (int)dst_right, (int)dst_bottom);
        final RectF rectF = new RectF(dst);
        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);
        canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
        canvas.drawBitmap(bitmap, src, dst, paint);
        return output;
    }
}


使用MVP三层编写数据

1. 登录model层  

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import okhttp3.OkHttpClient;

/**
 * 登录model层
 */

public class LoginModel {

    //https://www.zhaoapi.cn/user/login?mobile=18631090582&password=888888
    public void getLoginData(final String tel, String pwd, final ModelCallBack.LoginCallBack callBack){
        //使用okhttp请求,添加拦截器时把下面代码解释
        OkHttpClient ok = new OkHttpClient.Builder()
                .connectTimeout(20000, TimeUnit.SECONDS)
                .writeTimeout(20000,TimeUnit.SECONDS)
                .readTimeout(20000,TimeUnit.SECONDS)
                .addInterceptor(new LoggingInterceptor())
                .build();

        //使用Retrofit结合RxJava,okhttp封装类的单例模式
        Map<String,String> map = new HashMap<>();
        map.put("mobile",tel);
        map.put("password",pwd);

        RetrofitUnitl.getInstance("https://www.zhaoapi.cn",ok)
                .setCreate(GetDataInterface.class)
                .login(map)
                .subscribeOn(Schedulers.io())               //请求完成后在io线程中执行
                .observeOn(AndroidSchedulers.mainThread())  //最后在主线程中执行

        //进行事件的订阅,使用Consumer实现
        .subscribe(new Consumer<LoginBean>() {
            @Override
            public void accept(LoginBean loginBean) throws Exception {
                //请求成功时返回数据
                callBack.success(loginBean);
                System.out.println("m登录信息:" + loginBean.toString());
            }
        }, new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) throws Exception {
                callBack.failed(throwable);
            }
        });
    }
}


注册model层  

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit; 
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import okhttp3.OkHttpClient;

/**
 * 注册model层
 */

public class RegModel {

    //https://www.zhaoapi.cn/user/reg?mobile=18631090582&password=888888
    public void getRegData(final String tel, String pwd, final ModelCallBack.RegCallBack callBack){
        //使用okhttp请求,添加拦截器时把下面代码解释
        OkHttpClient ok = new OkHttpClient.Builder()
                .connectTimeout(20000, TimeUnit.SECONDS)
                .writeTimeout(20000,TimeUnit.SECONDS)
                .readTimeout(20000,TimeUnit.SECONDS)
                .addInterceptor(new LoggingInterceptor())
                .build();

        //使用Retrofit结合RxJava,okhttp封装类的单例模式
        Map<String,String> map = new HashMap<>();
        map.put("mobile",tel);
        map.put("password",pwd);

        RetrofitUnitl.getInstance("https://www.zhaoapi.cn",ok)
                .setCreate(GetDataInterface.class)
                .reg(map)
                .subscribeOn(Schedulers.io())               //请求完成后在io线程中执行
                .observeOn(AndroidSchedulers.mainThread())  //最后在主线程中执行

                //进行事件的订阅,使用Consumer实现
                .subscribe(new Consumer<RegBean>() {
                    @Override
                    public void accept(RegBean regBean) throws Exception {
                        //请求成功时返回数据
                        callBack.success(regBean);
                        System.out.println("m注册信息:" + regBean.toString());
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        callBack.failed(throwable);
                    }
                });
    }
}

个人信息model层  

import java.util.concurrent.TimeUnit;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import okhttp3.OkHttpClient;

/**
 * 个人信息model层
 */

public class PersonModel {

    //https://www.zhaoapi.cn/user/getUserInfo?uid=100
    public void getPersonData(int uid, final ModelCallBack.PersonCallBack callBack){
        //使用okhttp请求,添加拦截器时把下面代码解释
        OkHttpClient ok = new OkHttpClient.Builder()
                .connectTimeout(20000, TimeUnit.SECONDS)
                .writeTimeout(20000,TimeUnit.SECONDS)
                .readTimeout(20000,TimeUnit.SECONDS)
                .addInterceptor(new LoggingInterceptor())
                .build();

        //使用Retrofit结合RxJava,okhttp封装类的单例模式
        RetrofitUnitl.getInstance("https://www.zhaoapi.cn",ok)
                .setCreate(GetDataInterface.class)
                .person(uid)
                .subscribeOn(Schedulers.io())               //请求完成后在io线程中执行
                .observeOn(AndroidSchedulers.mainThread())  //最后在主线程中执行

                //进行事件的订阅,使用Consumer实现
                .subscribe(new Consumer<PersonInfoBean>() {
                    @Override
                    public void accept(PersonInfoBean personInfoBean) throws Exception {
                        //请求成功时返回数据
                        callBack.success(personInfoBean);
                        System.out.println("m个人信息:" + personInfoBean.toString());
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        callBack.failed(throwable);
                    }
                });
    }

}

model层接口

/**
 * MVP的三层编写步骤:
 * 1. 先写model层接口类,进行数据的存取
 */

public interface ModelCallBack {
    public interface LoginCallBack{
        //登录时,数据获取成功的方法,返回一个值表示登陆成功
        public void success(LoginBean loginBean);
        //登录时,数据获取失败的方法,返回一个int值响应码表示登陆失败
        public void failed(Throwable code);
    }

    public interface RegCallBack {
        //注册时,数据获取成功的方法,返回一个值表示登陆成功
        public void success(RegBean regBean);
        //注册时,数据获取失败的方法,返回一个int值响应码表示登陆失败
        public void failed(Throwable code);
    }

    //个人中心
    public interface PersonCallBack{
        void success(PersonInfoBean personBean);
        void failed(Throwable code);
    }
}
2.view层 

/**
 * MVP的三层编写步骤:
 * 2. View 层 数据展示类
 * View – 用户界面:View通常是指Activity、Fragment或者某个View控件,它含有一个Presenter成员变量。
 通常View需要实现一个逻辑接口,将View上的操作转交给Presenter进行实现,最后,Presenter 调用View逻辑接口将结果返回给View元素。
 */

public interface MyView {
    //登录页面由presenter层交互数据到view层MainActivity
    public interface LoginView{
        //登录时,数据获取成功的方法,返回一个值表示登陆成功
        void success(LoginBean loginBean);
        //登录时,数据获取失败的方法,返回一个int值响应码表示登陆失败
        void failed(int code);
    }

    //注册页面由presenter层到view层RegActivity
    public interface RegView{

        void failed(int code);
        void sucess(RegBean regBean);
    }

    //个人页面由presenter层到view层RegActivity
    public interface PersonView{
        void failed(int code);
        void sucess(PersonInfoBean personInfoBean);
    }
}

3.presenter层  

// Presenter层,进行view层与model数据的交互
/**
 * 登录p层
 */

public class LoginPresenter {

    LoginModel loginModel = new LoginModel();
    MyView.LoginView loginView;
    public LoginPresenter(MyView.LoginView loginView) {
        this.loginView = loginView;
    }

    public void getData(String tel, String pwd) {
        loginModel.getLoginData(tel,pwd, new ModelCallBack.LoginCallBack() {
            @Override
            public void success(LoginBean dengluBean) {
                loginView.success(dengluBean);
                System.out.println("登录p数据:"+dengluBean.toString());
            }

            @Override
            public void failed(Throwable code) {
                System.out.println("登录p错误:"+code);
            }
        });
    }
}

/**
 * 注册p层
 */

public class RegPresenter {
    RegModel regModel = new RegModel();
    MyView.RegView regView;
    public RegPresenter(MyView.RegView regView) {
        this.regView = regView;
    }

    public void getData(String tel, String pwd) {
        regModel.getRegData(tel,pwd, new ModelCallBack.RegCallBack() {

            @Override
            public void success(RegBean regBean) {
                regView.sucess(regBean);
                System.out.println("注册p数据:"+regBean.toString());
            }

            @Override
            public void failed(Throwable code) {
                System.out.println("注册p错误:"+code);
            }
        });
    }
}

/**
 * 个人p层
 */

public class PersonPresenter {

    PersonModel personModel = new PersonModel();
    MyView.PersonView personView;
    public PersonPresenter(MyView.PersonView personView) {
        this.personView = personView;
    }

    public void getData(int uid) {
        personModel.getPersonData(uid, new ModelCallBack.PersonCallBack() {
            @Override
            public void success(PersonInfoBean personInfoBean) {
                personView.sucess(personInfoBean);
                System.out.println("个人p数据:"+personInfoBean.toString());
            }

            @Override
            public void failed(Throwable code) {
                System.out.println("个人p错误:"+code);
            }
        });
    }
}

进入页面  MainActivity

import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;

//页面进入页
public class MainActivity extends AppCompatActivity {
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 0:
                    Intent intent = new Intent(MainActivity.this, PersonInfoActivity.class);
                    startActivity(intent);
                    finish();
                    break;

                case 1:
                    Intent intent2 = new Intent(MainActivity.this,LoginActivity.class);
                    startActivity(intent2);
                    finish();
                    break;

                default:
                    break;
            }
        }
    };


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

        //调用工具类判断保存的布尔值
        boolean b = SharedUtils.getBooleanData(MainActivity.this, "flag", false);

        if (b) {    //已经进入过,现在是第二次
            handler.sendEmptyMessageDelayed(0, 0);
        } else {        //现在是第一次
            SharedUtils.savaBooleanData(MainActivity.this, "flag", true);
            handler.sendEmptyMessageDelayed(1, 0);
        }
    }
}


登录 LoginActivity  

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

//用户登录
public class LoginActivity extends AppCompatActivity implements MyView.LoginView {
    @BindView(R.id.tel)
    EditText tel;
    @BindView(R.id.pwd)
    EditText pwd;
    @BindView(R.id.btn)
    Button btn;
    @BindView(R.id.reg)
    Button reg;
    private LoginPresenter presenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);

        //调用p层
        presenter = new LoginPresenter(this);

    }

    @Override
    public void success(LoginBean loginBean) {
        Toast.makeText(this, "登录结果:  " + loginBean.getMsg(), Toast.LENGTH_SHORT).show();

        if(loginBean.getMsg().equals("登录成功")){
            try {
                Thread.sleep(1000);
                Intent intent = new Intent(LoginActivity.this, PersonInfoActivity.class);
                startActivity(intent);
                finish();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void failed(int code) {
        Toast.makeText(this, "登录失败!请检查登录信息" + code, Toast.LENGTH_SHORT).show();
    }

    @OnClick({R.id.btn, R.id.reg})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.btn:
                if (!TextUtils.isEmpty(tel.getText().toString()) && !TextUtils.isEmpty(pwd.getText().toString())) {
                    //如果都不为空,请求接口
                    presenter.getData(tel.getText().toString(), pwd.getText().toString());
                } else {
                    Toast.makeText(this, "账号或密码不能为空", Toast.LENGTH_SHORT).show();
                }
                break;
            case R.id.reg:      //注册页
                Intent intent = new Intent(LoginActivity.this, RegActivity.class);
                startActivity(intent);
                break;
        }
    }
}

注册 RegActivity  

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

//注册用户信息
public class RegActivity extends AppCompatActivity implements MyView.RegView {
    @BindView(R.id.back)
    TextView back;
    @BindView(R.id.text)
    TextView text;
    @BindView(R.id.regTel)
    EditText regTel;
    @BindView(R.id.regPwd)
    EditText regPwd;
    @BindView(R.id.regNow)
    Button regNow;
    private RegPresenter presenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_reg);
        ButterKnife.bind(this);

        //调用p层
        presenter = new RegPresenter(this);
    }

    @Override
    public void failed(int code) {
        Toast.makeText(this, "注册失败!请检查网络"+ code, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void sucess(RegBean regBean) {
        Toast.makeText(this, "注册结果:      "+regBean.getMsg(), Toast.LENGTH_SHORT).show();

        if(regBean.getMsg().equals("注册成功")){
            try {
                Thread.sleep(2000);
                Toast.makeText(this, "即将跳转到登录页面", Toast.LENGTH_SHORT).show();
                finish();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    @OnClick({R.id.back, R.id.regNow})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.back:
                //点击返回按钮,返回到登录页面
                finish();
                break;

            case R.id.regNow: //注册按钮

                if (!TextUtils.isEmpty(regTel.getText().toString()) && !TextUtils.isEmpty(regPwd.getText().toString())) {

                    if (regTel.getText().toString().length() < 6){
                        Toast.makeText(this, "密码长度不能小于 6 位", Toast.LENGTH_SHORT).show();
                    }else {
                        // mvp请求注册的接口
                        presenter.getData(regTel.getText().toString(),regPwd.getText().toString());
                    }

                } else {
                    Toast.makeText(this, "账号或密码不能为空", Toast.LENGTH_SHORT).show();
                }
                break;
        }
    }
}

个人 PersonInfoActivity    

import android.Manifest;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.facebook.drawee.view.SimpleDraweeView;
import java.io.File;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

//用户个人信息页面
public class PersonInfoActivity extends AppCompatActivity implements MyView.PersonView {
    @BindView(R.id.headPhoto)
    SimpleDraweeView headPhoto;
    @BindView(R.id.userName)
    TextView userName;
    @BindView(R.id.nickName)
    TextView nickName;
    @BindView(R.id.outLogin)
    Button outLogin;
    protected static final int CHOOSE_PICTURE = 0;
    protected static final int TAKE_PICTURE = 1;
    private static final int CROP_SMALL_PICTURE = 2;
    protected static Uri tempUri;
    private PersonPresenter dataPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_person_info);
        ButterKnife.bind(this);

        //从presenter调用个人中心的接口
        dataPresenter = new PersonPresenter(this);
        dataPresenter.getData(100);
    }

    @Override
    public void failed(int code) {
        Toast.makeText(PersonInfoActivity.this,"数据错误:"+code,Toast.LENGTH_SHORT).show();
    }

    @Override
    public void sucess(PersonInfoBean personInfoBean) {
        Toast.makeText(PersonInfoActivity.this,"个人数据:"+personInfoBean.getMsg()+"            "+personInfoBean.toString(),Toast.LENGTH_SHORT).show();

        //设置个人信息
        if(personInfoBean.getMsg().equals("获取用户信息成功")) {
            headPhoto.setImageURI(personInfoBean.getData().getIcon());
            nickName.setText(personInfoBean.getData().getNickname());
            userName.setText(personInfoBean.getData().getUsername());
        }
    }

    @OnClick({R.id.headPhoto, R.id.userName, R.id.nickName, R.id.outLogin})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.headPhoto:    //上传头像
                showChoosePicDialog(view);
                break;

            case R.id.outLogin:
                //点击退出登录按钮,返回到登录页面
                Intent intent = new Intent(PersonInfoActivity.this, LoginActivity.class);
                startActivity(intent);
                finish();
                break;
        }
    }

    /**
     * 显示修改头像的对话框
     */
    public void showChoosePicDialog(View v) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("设置头像");
        String[] items = { "选择本地照片", "拍照" };
        builder.setNegativeButton("取消", null);
        builder.setItems(items, new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                switch (which) {
                    case CHOOSE_PICTURE: // 选择本地照片
                        Intent openAlbumIntent = new Intent(
                                Intent.ACTION_GET_CONTENT);
                        openAlbumIntent.setType("image/*");
                        startActivityForResult(openAlbumIntent, CHOOSE_PICTURE);
                        break;
                    case TAKE_PICTURE: // 拍照
                        takePicture();
                        break;
                }
            }
        });
        builder.create().show();
    }

    private void takePicture() {
        String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
        if (Build.VERSION.SDK_INT >= 23) {
            // 需要申请动态权限
            int check = ContextCompat.checkSelfPermission(this, permissions[0]);
            // 权限是否已经 授权 GRANTED---授权  DINIED---拒绝
            if (check != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
            }
        }
        Intent openCameraIntent = new Intent(
                MediaStore.ACTION_IMAGE_CAPTURE);
        File file = new File(Environment
                .getExternalStorageDirectory(), "image.jpg");
        //判断是否是AndroidN以及更高的版本
        if (Build.VERSION.SDK_INT >= 24) {
            openCameraIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            tempUri = FileProvider.getUriForFile(PersonInfoActivity.this, "com.lt.uploadpicdemo.fileProvider", file);
        } else {
            tempUri = Uri.fromFile(new File(Environment
                    .getExternalStorageDirectory(), "image.jpg"));
        }
        // 指定照片保存路径(SD卡),image.jpg为一个临时文件,每次拍照后这个图片都会被替换
        openCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, tempUri);
        startActivityForResult(openCameraIntent, TAKE_PICTURE);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK) { // 如果返回码是可以用的
            switch (requestCode) {
                case TAKE_PICTURE:
                    startPhotoZoom(tempUri); // 开始对图片进行裁剪处理
                    break;
                case CHOOSE_PICTURE:
                    startPhotoZoom(data.getData()); // 开始对图片进行裁剪处理
                    break;
                case CROP_SMALL_PICTURE:
                    if (data != null) {
                        setImageToView(data); // 让刚才选择裁剪得到的图片显示在界面上
                    }
                    break;
            }
        }
    }

    /**
     * 裁剪图片方法实现
     *
     * @param uri
     */
    protected void startPhotoZoom(Uri uri) {
        if (uri == null) {
            Log.i("tag", "The uri is not exist.");
        }
        tempUri = uri;
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(uri, "image/*");
        // 设置裁剪
        intent.putExtra("crop", "true");
        // aspectX aspectY 是宽高的比例
        intent.putExtra("aspectX", 1);
        intent.putExtra("aspectY", 1);
        // outputX outputY 是裁剪图片宽高
        intent.putExtra("outputX", 150);
        intent.putExtra("outputY", 150);
        intent.putExtra("return-data", true);
        startActivityForResult(intent, CROP_SMALL_PICTURE);
    }

    /**
     * 保存裁剪之后的图片数据
     *
     * @param
     */
    protected void setImageToView(Intent data) {
        Bundle extras = data.getExtras();
        if (extras != null) {
            Bitmap photo = extras.getParcelable("data");

            photo = ImageUtils.toRoundBitmap(photo); // 这个时候的图片已经被处理成圆形的了
            headPhoto.setImageBitmap(photo);
            uploadPic(photo);
        }
    }

    private void uploadPic(Bitmap bitmap) {
        // 上传至服务器
        // ... 可以在这里把Bitmap转换成file,然后得到file的url,做文件上传操作
        // 注意这里得到的图片已经是圆形图片了
        // bitmap是没有做个圆形处理的,但已经被裁剪了
        String imagePath = ImageUtils.savePhoto(bitmap, Environment
                .getExternalStorageDirectory().getAbsolutePath(), String
                .valueOf(System.currentTimeMillis()));
        Log.e("imagePath", imagePath+"");
        if(imagePath != null){
            // 拿着imagePath上传了

            Log.d("TAG","imagePath:"+imagePath);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

        } else {
            // 没有获取 到权限,从新请求,或者关闭app
            Toast.makeText(this, "需要存储权限", Toast.LENGTH_SHORT).show();
        }
    }
}


布局

登录布局 activity_main.xml    

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:text="登录"
        android:padding="20dp"
        android:textSize="26sp"
        android:layout_gravity="center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"    />

    <View
        android:background="#000"
        android:visibility="visible"
        android:layout_height="1dp"
        android:layout_width="match_parent"></View>

    <EditText
        android:id="@+id/tel"
        android:hint="请输入手机号"
        android:layout_marginTop="28dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"  />

    <EditText
        android:id="@+id/pwd"
        android:hint="请输入密码"
        android:layout_marginTop="28dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"  />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <Button
            android:text="登录"
            android:id="@+id/btn"
            android:background="#1E90FF"
            android:layout_marginLeft="78dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="78dp"
            android:layout_alignParentTop="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:layout_marginTop="54dp" />

        <Button
            android:text="注册"
            android:id="@+id/reg"
            android:background="#1E90FF"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_marginRight="83dp"
            android:layout_marginEnd="83dp"
            android:layout_alignTop="@+id/btn"
            android:layout_alignParentRight="true"
            android:layout_alignParentEnd="true" />

    </RelativeLayout>

</LinearLayout>

注册布局 activity_reg.xml    

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:background="@drawable/back_arrow_black"
            android:padding="20dp"
            android:id="@+id/back"
            android:textSize="40sp"
            android:layout_width="28dp"
            android:layout_height="28dp"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"/>

        <TextView
            android:text="注册"
            android:padding="20dp"
            android:textSize="26sp"
            android:id="@+id/text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"    />

        <View
            android:background="#000"
            android:visibility="visible"
            android:layout_height="1dp"
            android:layout_below="@+id/text"
            android:layout_width="match_parent"></View>
    </RelativeLayout>

    <EditText
        android:id="@+id/regTel"
        android:hint="请输入手机号"
        android:layout_marginTop="28dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"  />

    <EditText
        android:id="@+id/regPwd"
        android:hint="请输入密码"
        android:layout_marginTop="28dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"  />

    <Button
        android:text="立即注册"
        android:id="@+id/regNow"
        android:background="#1E90FF"
        android:layout_marginTop="28dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"/>

</LinearLayout>

个人布局  activity_person_info.xml    

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"  >

    <RelativeLayout
        android:id="@+id/reative_01"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:padding="20dp"
            android:text="个人信息"
            android:textSize="26sp"
            android:id="@+id/text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"    />

        <View
            android:background="#000"
            android:visibility="visible"
            android:layout_height="1dp"
            android:layout_below="@+id/text"
            android:layout_width="match_parent"></View>
    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/reative_02"
        android:layout_below="@+id/reative_01"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:text="头像"
            android:padding="20dp"
            android:textSize="26sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"/>

        <com.facebook.drawee.view.SimpleDraweeView
            android:padding="20dp"
            fresco:roundAsCircle="true"
            android:id="@+id/headPhoto"
            android:layout_width="108dp"
            android:layout_height="108dp"
            android:layout_centerVertical="true"
            android:layout_alignParentRight="true"
            fresco:actualImageScaleType="focusCrop"
            fresco:placeholderImageScaleType="fitCenter"
            fresco:placeholderImage="@drawable/app_default"
            fresco:failureImageScaleType="fitCenter"
            fresco:failureImage="@drawable/load_error_image"  />
    </RelativeLayout>
    <View
        android:background="#000"
        android:visibility="visible"
        android:layout_height="1dp"
        android:layout_below="@+id/reative_02"
        android:layout_width="match_parent"></View>

    <RelativeLayout
        android:id="@+id/reative_03"
        android:layout_below="@+id/reative_02"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:text="用户名"
            android:padding="20dp"
            android:textSize="26sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"/>

        <TextView
            android:text="用户名"
            android:padding="20dp"
            android:id="@+id/userName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_alignParentRight="true"/>
    </RelativeLayout>
    <View
        android:background="#000"
        android:visibility="visible"
        android:layout_height="1dp"
        android:layout_below="@+id/reative_03"
        android:layout_width="match_parent"></View>

    <RelativeLayout
        android:id="@+id/reative_04"
        android:layout_below="@+id/reative_03"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:text="昵称"
            android:padding="20dp"
            android:textSize="26sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"/>

        <TextView
            android:text="问天"
            android:padding="20dp"
            android:id="@+id/nickName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_alignParentRight="true"/>
    </RelativeLayout>
    <View
        android:id="@+id/view"
        android:background="#000"
        android:visibility="visible"
        android:layout_height="1dp"
        android:layout_below="@+id/reative_04"
        android:layout_width="match_parent"></View>

    <Button
        android:text="退出登录"
        android:id="@+id/outLogin"
        android:background="#1E90FF"
        android:layout_marginTop="88dp"
        android:layout_below="@+id/view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true" />
</RelativeLayout>

Fresco加载图片的素材:

1. app_deafult.jpg



2. load_error_image.jpg



3. back_arrowblack.png





猜你喜欢

转载自blog.csdn.net/xxb52306/article/details/79020101