使用MVP注册登录模块+封装的OKhttp,拦截器+QQ第三方登录+RecyclerView+SpringView上拉加载下拉刷新网络数据

需求:使用MVP框架

1登录注册功能,登录页面和注册页面分别用一个Fragment实现,

点击对应按钮时动态切换Fragment的显示,

使用sqlite操作模拟登录注册的网络请求,

登录注册使用MVP模式完成,正确创建View层接口,

正确创建Model层接口和实现

正确使用Presenter完成viewmodel层的逻辑实现

        2、登录成功后,跳转到主界面,实现页面效果

点击QQ登录”,实现第三方登录,并获取用户的信息,把头像、姓名、等级、地址显示到界面上。

3、点击列表选项卡,进入列表页面,使用线程安全的单例模式封装OkHttp网络请求,把OkHttp回调封装在主线程中执行,

     添加拦截器(必须添加指定拦截器LoggingInterceptor.java,否则数 据无法加载

4把接口地址请求回来的数据封装成JavaBean,

使用RecyclerView加载数据,

     根据offset参数实现下拉刷新上拉加载(可使用第三方,如xRecyclerView或        SwipeRefreshLayout

   5. 添加RecyclerView的单击事件,

点击RecyclerView控件后把对应条目的标题传到详情Activity并显示(详情页效果图未提供,里面就一个TextView,接收到数据后,给TextView设置值即可)

   6. 添加RecyclerView长按事件,长按删除该条目


1.  导包:gson包,ImageLoader包,open_sdk_r5886_lite.jar包用于第三方QQ登录


2. 添加依赖:

(1)butterknife自动生成控件id和点击事件:

     compile 'com.jakewharton:butterknife:7.0.0'

(2)okhttp依赖:
     compile 'com.squareup.okhttp3:okhttp:3.9.0'

(3)recyclerview依赖(我自己的版本需要把SDK改为25版本):

     compile 'com.android.support:recyclerview-v7:25.3.1'
     compile 'com.yqritc:recyclerview-flexibledivider:1.4.0'

(4)springview依赖

     compile 'com.liaoinstan.springview:library:1.3.0'

一 . 首先编写OKhttp的封装类

import java.io.File;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
/**
 * Okhttp 单例 范型的封装
 */
public class OkhttpUtils {
    private static OkhttpUtils okhttpUtils = null ;
    private OkhttpUtils(){
    }

    public static OkhttpUtils getInstance(){
        if(okhttpUtils == null){
            okhttpUtils = new OkhttpUtils();
            client = new OkHttpClient.Builder()
                    .readTimeout(20, TimeUnit.SECONDS)
                    .writeTimeout(20,TimeUnit.SECONDS)
                    .connectTimeout(20,TimeUnit.SECONDS)
                    .addInterceptor(new LoggingInterceptor())
                    .build();
        }
        return okhttpUtils ;
    }

    private static OkHttpClient client ;

    public void asy(Map<String,String> params,String url,AbstractUiCallBack callBack){
        Request request = null ;
        if(params != null){
            FormBody.Builder builder = new FormBody.Builder() ;
            for(Map.Entry<String,String> entry : params.entrySet()){
                builder.add(entry.getKey(),entry.getValue());
            }
            FormBody body =  builder.build();
            request = new Request.Builder()
                    .url(url)
                    .post(body)
                    .build();
        } else {
            request = new Request.Builder()
                    .url(url)
                    .build();
        }
        client.newCall(request).enqueue(callBack);
    }

    private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");

    public static void postFile(Map<String,String> map, String url, File file,AbstractUiCallBack callBack) {

        String[] array = file.getAbsolutePath().split("\\/");

        MultipartBody.Builder builder = new MultipartBody.Builder();
        builder.setType(MultipartBody.FORM);

        for (Map.Entry<String, String> entry : map.entrySet()) {
            builder.addFormDataPart(entry.getKey(), entry.getValue());
        }
        builder.addFormDataPart("imageFileName", array[array.length - 1]);

        if (file.exists() && file.length() > 0) {
            builder.addFormDataPart("image", array[array.length - 1], RequestBody.create(MEDIA_TYPE_PNG, file));
        }
        MultipartBody body = builder.build();

        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        client.newCall(request).enqueue(callBack);
    }
}

   OKhttp封装需实现的接口类   

import android.os.Handler;
import android.os.Looper;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
/**
 *  * Okhttp 单例 范型的封装
 */
public  abstract  class AbstractUiCallBack<T> implements Callback {
    /**
     * 成功回调
     * @param t
     */
    public abstract void success(T t);

    /**
     * 失败回调
     * @param e
     */
    public abstract void failure(Exception e);

    private Handler handler = null ;
    private Class clazz ;

    public AbstractUiCallBack(){
        handler = new Handler(Looper.getMainLooper());

        //  得到的是一个 AbstractUiCallBack<T> 的Type
       Type type =  getClass().getGenericSuperclass() ;

        // 得到的是T的实际Type
       Type [] arr =  ((ParameterizedType)type).getActualTypeArguments() ;

        clazz = (Class) arr[0] ;
    }

    @Override
    public void onFailure(Call call, IOException e) {
        failure(e);
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        try {
            String result = response.body().string();
            System.out.println("result = " + result);
            Gson gson = new Gson();

            final T t = (T) gson.fromJson(result,clazz);

            handler.post(new Runnable() {
                @Override
                public void run() {
                    success(t);
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
            failure(e);
        } catch (JsonSyntaxException e) {
            e.printStackTrace();
            failure(e);
        }
    }
}

二. 拦截器类

package com.bwie.secondweek_moni.okhttp;
import android.os.Build;
import java.io.IOException;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;

/**
 * Created by 笔片 on 2017/10/16.
 * 网络拦截器
 */

public class LoggingInterceptor implements Interceptor{
    private static final String UA = "User-Agent";
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request()
                .newBuilder()
                .addHeader(UA, makeUA())
                .build();
        return chain.proceed(request);
    }
    private String makeUA() {
        String s = Build.BRAND + "/" + Build.MODEL + "/" + Build.VERSION.RELEASE;
        return Build.BRAND + "/" + Build.MODEL + "/" + Build.VERSION.RELEASE;
    }
}


三. model层

package com.bwie.secondweek_moni.model;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import com.bwie.secondweek_moni.sqlite.MyHelper;
import com.bwie.secondweek_moni.view_jiekou.LoginModelCallBack;
import com.bwie.secondweek_moni.view_jiekou.RegModelCallBack;

//model层模块,即对数据库操作的类
public class MyModel {
    //注册数据时的 访问数据库方法
    public void reg(Context context, String tel, String pwd, RegModelCallBack regModelCallBack){
        //注册时添加数据库数据
        MyHelper myHelper = new MyHelper(context);
        SQLiteDatabase database = myHelper.getWritableDatabase();
        database.execSQL("insert into user(tel,pwd) values(?,?)",new String[]{tel,pwd});
        database.close();
        //注册成功的回调
        regModelCallBack.regSuccess();
    }

    //登录时的 访问数据库方法
    public void login(Context context, String tel, String pwd, LoginModelCallBack loginModelCallBack){
        //登录时查询数据库数据
        MyHelper myHelper = new MyHelper(context);
        SQLiteDatabase database = myHelper.getWritableDatabase();
        Cursor cursor = database.rawQuery("select * from user where tel = ? and pwd = ?", new String[]{tel, pwd});
        if (cursor.moveToNext()){
            //数据查询到时就成功回调方法
            loginModelCallBack.loginSuccess();
        }else {
            loginModelCallBack.loginFailed();
        }
    }
}

四. view层

1. 登录时model层接口

package com.bwie.secondweek_moni.view_jiekou;

//登录时的接口
public interface LoginModelCallBack {
    public void loginSuccess();
    public void loginFailed();
}

2. 登录时view层接口

package com.bwie.secondweek_moni.view_jiekou;

//登录时在view层回调判断数据的接口
public interface LoginViewCallBack {
    //登陆判断非空
    public void loginTelEmpty();
    public void loginPwdEmpty();
    public void loginSuccess();
    public void loginFailed();
}

3. 注册时model层接口

package com.bwie.secondweek_moni.view_jiekou;

//注册时的接口
public interface RegModelCallBack {
    public void regSuccess();
}
4. 注册时view层接口

package com.bwie.secondweek_moni.view_jiekou;

//注册时在view层回调判断数据的接口
public interface RegViewCallBack {
    //注册判断非空
    public void regTelEmpty();
    public void regPwdEmpty();
    public void regSuccess();
    public void regFailed();
}

五. presenter层

package com.bwie.secondweek_moni.presenter;
import android.support.v4.app.FragmentActivity;
import android.text.TextUtils;
import com.bwie.secondweek_moni.model.MyModel;
import com.bwie.secondweek_moni.view_jiekou.LoginModelCallBack;
import com.bwie.secondweek_moni.view_jiekou.RegModelCallBack;

//Presenter层 调用model中的注册 和 登录的方法
public class MyPresenter {
    FragmentActivity activity;
    //获取登录和注册时view层数据,声明为当前变量
    LoginViewCallBack loginViewCallBack;
    RegViewCallBack regViewCallBack;
    public MyPresenter(FragmentActivity activity, LoginViewCallBack loginViewCallBack, RegViewCallBack regViewCallBack) {
        this.activity = activity;
        this.loginViewCallBack = loginViewCallBack;
        this.regViewCallBack = regViewCallBack;
    }

    //获取model层
    MyModel model = new MyModel();

    //注册时在view层回调判断数据的接口
    public interface RegViewCallBack {
        //注册判断非空
        public void regTelEmpty();
        public void regPwdEmpty();
        public void regSuccess();
        public void regFailed();
    }

    //登录时在view层回调判断数据的接口
    public interface LoginViewCallBack {
        //登陆判断非空
        public void loginTelEmpty();
        public void loginPwdEmpty();
        public void loginSuccess();
        public void loginFailed();
    }

    //在Presenter层逻辑判断注册时非空
    public void reg_PanDuan(String tel,String pwd){
        if (TextUtils.isEmpty(tel)){
            //回调判断注册手机号时的接口方法
            regViewCallBack.regTelEmpty();
            return;
        }else if (TextUtils.isEmpty(pwd)){
            //回调判断注册密码时的接口方法
            regViewCallBack.regPwdEmpty();
            return;
        }
        //如果注册成功就调用注册接口的成功方法
        model.reg(activity, tel, pwd, new RegModelCallBack() {
            @Override
            public void regSuccess() {
                regViewCallBack.regSuccess();
            }
        });
    }

    //在Presenter层逻辑判断登录时非空
    public void login_PanDuan(String tel,String pwd){
        if (TextUtils.isEmpty(tel)){
            //回调判断登录手机号时的接口方法
            loginViewCallBack.loginTelEmpty();
            return;
        }else if (TextUtils.isEmpty(pwd)){
            //回调判断登录密码时的接口方法
            loginViewCallBack.loginPwdEmpty();
            return;
        }
        //调用登录接口的方法
        model.login(activity, tel, pwd, new LoginModelCallBack() {
            @Override
            public void loginSuccess() {
                loginViewCallBack.loginSuccess();
            }

            @Override
            public void loginFailed() {
                loginViewCallBack.loginFailed();
            }
        });
    }
}


六. imageloader工具类及其全局初始化配置

(1)全局初始化配置类:

package com.bwie.secondweek.util;

import android.app.Application;
//全局初始化Application类
public class BaseApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        //配置imageLoader
        ImageLoaderUtil.init(this);
    }
}

(2)imageloader工具类:

package com.bwie.secondweek.util;
import android.content.Context;
import android.graphics.Bitmap;
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache;
import com.nostra13.universalimageloader.cache.disc.naming.HashCodeFileNameGenerator;
import com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
import com.nostra13.universalimageloader.core.decode.BaseImageDecoder;
import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer;
import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer;
import com.nostra13.universalimageloader.core.download.BaseImageDownloader;
import com.nostra13.universalimageloader.utils.StorageUtils;

import java.io.File;
public class ImageLoaderUtil {
    /**
     * 初始化imageLoader
     * @param context
     */
    public static void init(Context context) {
        //1.获取配置config对象
        File cacheDir = StorageUtils.getCacheDirectory(context);  //缓存文件夹路径

        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)

                .threadPoolSize(3) // default  线程池内加载的数量
                .threadPriority(Thread.NORM_PRIORITY - 2) // default 设置当前线程的优先级
                .tasksProcessingOrder(QueueProcessingType.FIFO) // default
                .denyCacheImageMultipleSizesInMemory()
                .memoryCache(new LruMemoryCache(2 * 1024 * 1024)) //可以通过自己的内存缓存实现
                .memoryCacheSize(2 * 1024 * 1024)  // 内存缓存的最大值
                .memoryCacheSizePercentage(13) // default
                .diskCache(new UnlimitedDiscCache(cacheDir)) // default 可以自定义缓存路径
                .diskCacheSize(50 * 1024 * 1024) // 50 Mb sd卡(本地)缓存的最大值
                .diskCacheFileCount(100)  // 可以缓存的文件数量
                // default为使用HASHCODE对UIL进行加密命名, 还可以用MD5(new Md5FileNameGenerator())加密
                .diskCacheFileNameGenerator(new HashCodeFileNameGenerator())
                .imageDownloader(new BaseImageDownloader(context)) // default
                .imageDecoder(new BaseImageDecoder(true)) // default
                .defaultDisplayImageOptions(DisplayImageOptions.createSimple()) // default
                .writeDebugLogs() // 打印debug log
                .build(); //开始构建


        //2.初始化配置...ImageLoader.getInstance()图片加载器的对象,单例模式
        ImageLoader.getInstance().init(config);
    }

    /**
     * imageLoader加载图片的默认选项
     * @return
     */
    public static DisplayImageOptions getDefaultOption(){

        DisplayImageOptions options = new DisplayImageOptions.Builder()
                .showImageOnLoading(R.mipmap.ic_launcher) // 设置图片下载期间显示的默认图片
                .showImageForEmptyUri(R.mipmap.ic_launcher) // 设置图片Uri为空或是错误的时候显示的图片
                .showImageOnFail(R.mipmap.ic_launcher) // 设置图片加载或解码过程中发生错误显示的图片
                .resetViewBeforeLoading(true)  // default 设置图片在加载前是否重置、复位
                .delayBeforeLoading(1000)  // 下载前的延迟时间
                .cacheInMemory(true) // default  设置下载的图片是否缓存在内存中
                .cacheOnDisk(true) // default  设置下载的图片是否缓存在SD卡中

                .considerExifParams(true) // default
                .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default 设置图片以如何的编码方式显示
                .bitmapConfig(Bitmap.Config.RGB_565) // default 设置图片的解码类型

                .displayer(new SimpleBitmapDisplayer()) // default  还可以设置圆角图片new RoundedBitmapDisplayer(20)

                .build();

        return options;
    }

    /**
     * imageLoader加载圆角图片....指定圆角的大小
     * @return
     */
    public static DisplayImageOptions getRoundedOption(int corner){

        DisplayImageOptions options = new DisplayImageOptions.Builder()
                .showImageOnLoading(R.mipmap.ic_launcher) // 设置图片下载期间显示的图片
                .showImageForEmptyUri(R.mipmap.ic_launcher) // 设置图片Uri为空或是错误的时候显示的图片
                .showImageOnFail(R.mipmap.ic_launcher) // 设置图片加载或解码过程中发生错误显示的图片
                .resetViewBeforeLoading(true)  // default 设置图片在加载前是否重置、复位
                .delayBeforeLoading(1000)  // 下载前的延迟时间
                .cacheInMemory(true) // default  设置下载的图片是否缓存在内存中
                .cacheOnDisk(true) // default  设置下载的图片是否缓存在SD卡中

                .considerExifParams(true) // default
                .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default 设置图片以如何的编码方式显示
                .bitmapConfig(Bitmap.Config.RGB_565) // default 设置图片的解码类型
                .displayer(new RoundedBitmapDisplayer(corner)) // default  还可以设置圆角图片new RoundedBitmapDisplayer(20)

                .build();

        return options;
    }

}

七. 数据接口封装的bean类(根据自己需要定义)

1.一个是第三方登录QQ时返回的个人数据bean类;

2.一个是网络请求数据时返回的bean类;

八. 数据库创建类

package com.bwie.secondweek_moni.sqlite;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

//数据库
public class MyHelper extends SQLiteOpenHelper{
    public MyHelper(Context context) {
        super(context, "user.db", null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        //创建数据库
        db.execSQL("create table user(tel varchar(20),pwd password(20))");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

九. 主功能代码MainActivity

package com.bwie.secondweek_moni;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import com.bwie.secondweek_moni.fragment.Login_Fragment;
import com.bwie.secondweek_moni.fragment.Reg_Fragment;
import java.util.ArrayList;
import java.util.List;
import butterknife.Bind;
import butterknife.ButterKnife;
public class MainActivity extends AppCompatActivity {
    @Bind(R.id.button_person)
    RadioButton buttonPerson;
    @Bind(R.id.button_list)
    RadioButton buttonList;
    @Bind(R.id.groups)
    RadioGroup groups;
    @Bind(R.id.main_viewPager)
    ViewPager mainViewPager;
    private List<Fragment> list;

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

        //定义集合添加数据
        list = new ArrayList<>();
        list.add(new Login_Fragment());
        list.add(new Reg_Fragment());

        //加入此行代码可使当页数据一直有效显示,不会随着页面滑动而消失
        mainViewPager.setOffscreenPageLimit(list.size());

        //设置适配器
        mainViewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
            @Override
            public Fragment getItem(int position) {
                return list.get(position);
            }

            @Override
            public int getCount() {
                return list.size();
            }
        });

        //设置viewpager的滑动监听事件
        mainViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }

            @Override
            public void onPageSelected(int position) {
                groups.check(groups.getChildAt(position).getId());
            }

            @Override
            public void onPageScrollStateChanged(int state) {
            }
        });
        //设置button按钮的监听事件
        groups.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                switch (checkedId) {
                    case R.id.button_person:
                        mainViewPager.setCurrentItem(0, false);
                        break;
                    case R.id.button_list:
                        mainViewPager.setCurrentItem(1, false);
                        break;
                    default:
                        break;
                }
            }
        });
    }
}

9.1 对应的登录页面fragment:

package com.bwie.secondweek_moni.fragment;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.bwie.secondweek_moni.R;
import com.bwie.secondweek_moni.activity.SecondActivity;
import com.bwie.secondweek_moni.activity.ThirdActivity;
import com.bwie.secondweek_moni.presenter.MyPresenter;

import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;

//登录页
public class Login_Fragment extends Fragment {
    @Bind(R.id.tel_Login)
    EditText telLogin;
    @Bind(R.id.pwd_Login)
    EditText pwdLogin;
    @Bind(R.id.login)
    Button login;
    @Bind(R.id.qqLogin)
    Button qqLogin;
    private MyPresenter myPresenter;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.login_fragment, container, false);
        ButterKnife.bind(this, view);
        return view;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        myPresenter = new MyPresenter(getActivity(), new MyPresenter.LoginViewCallBack() {
            @Override
            public void loginTelEmpty() {
                Toast.makeText(getActivity(),"登录时 手机号不能为空",Toast.LENGTH_SHORT).show();
            }

            @Override
            public void loginPwdEmpty() {
                Toast.makeText(getActivity(),"登录时 密码不能为空",Toast.LENGTH_SHORT).show();
            }

            @Override
            public void loginSuccess() {
                Toast.makeText(getActivity(),"登录成功!即将跳转到主页面",Toast.LENGTH_SHORT).show();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Intent intent = new Intent(getActivity(), ThirdActivity.class);
                startActivity(intent);
            }

            @Override
            public void loginFailed() {
                Toast.makeText(getActivity(),"登录失败!用户信息输入错误...",Toast.LENGTH_SHORT).show();
            }
        }, new MyPresenter.RegViewCallBack() {
            @Override
            public void regTelEmpty() {
            }

            @Override
            public void regPwdEmpty() {
            }

            @Override
            public void regSuccess() {
            }

            @Override
            public void regFailed() {
            }
        });
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        ButterKnife.unbind(this);
    }

    @OnClick({R.id.login,R.id.qqLogin})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.login:    //登录按钮的非空判断
                myPresenter.login_PanDuan(telLogin.getText().toString(),pwdLogin.getText().toString());
                break;
            case R.id.qqLogin:    //第三方QQ登录
                Intent intent = new Intent(getActivity(), SecondActivity.class);
                startActivity(intent);
                break;
        }
    }
}
9.2 对应的注册页面fragment:

package com.bwie.secondweek_moni.fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.bwie.secondweek_moni.R;
import com.bwie.secondweek_moni.presenter.MyPresenter;
import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;

//注册页
public class Reg_Fragment extends Fragment {
    @Bind(R.id.tel_Reg)
    EditText telReg;
    @Bind(R.id.pwd_Reg)
    EditText pwdReg;
    @Bind(R.id.reg)
    Button reg;
    private MyPresenter myPresenter;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.reg_fragment, container, false);
        ButterKnife.bind(this, view);
        return view;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        myPresenter = new MyPresenter(getActivity(), new MyPresenter.LoginViewCallBack() {
            @Override
            public void loginTelEmpty() {
            }

            @Override
            public void loginPwdEmpty() {
            }

            @Override
            public void loginSuccess() {
            }

            @Override
            public void loginFailed() {
            }
        }, new MyPresenter.RegViewCallBack() {
            @Override
            public void regTelEmpty() {
                Toast.makeText(getActivity(),"注册时 手机号不能为空",Toast.LENGTH_SHORT).show();
            }

            @Override
            public void regPwdEmpty() {
                Toast.makeText(getActivity(),"注册时 密码不能为空",Toast.LENGTH_SHORT).show();
            }

            @Override
            public void regSuccess() {
                Toast.makeText(getActivity(),"注册成功!请前往登录页面!",Toast.LENGTH_SHORT).show();
            }

            @Override
            public void regFailed() {
                Toast.makeText(getActivity(),"注册失败!请重新注册!",Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        ButterKnife.unbind(this);
    }

    @OnClick(R.id.reg)
    public void onViewClicked() {   //点击注册按钮 调用presenter层去逻辑判断非空
        myPresenter.reg_PanDuan(telReg.getText().toString(),pwdReg.getText().toString());
    }
}

十. 第三方QQ登录页

package com.bwie.secondweek_moni.activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.bwie.secondweek_moni.R;
import com.bwie.secondweek_moni.bean.UserBean;
import com.google.gson.Gson;
import com.tencent.connect.UserInfo;
import com.tencent.connect.auth.QQToken;
import com.tencent.connect.common.Constants;
import com.tencent.tauth.IUiListener;
import com.tencent.tauth.Tencent;
import com.tencent.tauth.UiError;
import org.json.JSONException;
import org.json.JSONObject;

//QQ第三方登录页
public class SecondActivity extends AppCompatActivity {
    private static final String APP_ID = "1105602574";//官方获取的APPID
    private static final String TAG = "MainActivity";
    private BaseUiListener mIUiListener;
    private UserInfo mUserInfo;
    private Tencent mTencent;

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

        //传入参数APPID和全局Context上下文
        mTencent = Tencent.createInstance(APP_ID,SecondActivity.this.getApplicationContext());
    }

    public void qq_Second(View v){
        /**通过这句代码,SDK实现了QQ的登录,这个方法有三个参数,第一个参数是context上下文,第二个参数SCOPO 是一个String类型的字符串,表示一些权限
         官方文档中的说明:应用需要获得哪些API的权限,由“,”分隔。例如:SCOPE = “get_user_info,add_t”;所有权限用“all”
         第三个参数,是一个事件监听器,IUiListener接口的实例,这里用的是该接口的实现类 */
        mIUiListener = new BaseUiListener();
        //all表示获取所有权限
        mTencent.login(SecondActivity.this,"all", mIUiListener);
    }

    /**
     * 自定义监听器实现IUiListener接口后,需要实现的3个方法
     * onComplete完成 onError错误 onCancel取消
     */
    private class BaseUiListener implements IUiListener {
        @Override
        public void onComplete(Object response) {
            Toast.makeText(SecondActivity.this, "授权成功", Toast.LENGTH_SHORT).show();
            Log.e(TAG, "response:" + response);
            JSONObject obj = (JSONObject) response;
            try {
                String openID = obj.getString("openid");
                String accessToken = obj.getString("access_token");
                String expires = obj.getString("expires_in");
                mTencent.setOpenId(openID);
                mTencent.setAccessToken(accessToken,expires);
                QQToken qqToken = mTencent.getQQToken();
                mUserInfo = new UserInfo(getApplicationContext(),qqToken);
                mUserInfo.getUserInfo(new IUiListener() {
                    @Override
                    public void onComplete(final Object response) {
                        //用户登录成功后会返回用户的数据,在此可以封装成bean类,跳转传值,设置用户的基本信息
                        Log.i(TAG,"登录成功"+response.toString());

                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                //跳转传值,设置用户信息
                                UserBean userBean = new Gson().fromJson(response.toString(), UserBean.class);
                                Intent intent = new Intent(SecondActivity.this,ThirdActivity.class);
                                intent.putExtra("headPhoto",userBean.getFigureurl_qq_1());
                                intent.putExtra("name",userBean.getNickname());
                                intent.putExtra("gender",userBean.getGender());
                                String province = userBean.getProvince();
                                String city = userBean.getCity();
                                String address = province + city;
                                intent.putExtra("address",address);
                                startActivity(intent);
                            }
                        });
                    }

                    @Override
                    public void onError(UiError uiError) {
                        Log.e(TAG,"登录失败"+uiError.toString());
                    }

                    @Override
                    public void onCancel() {
                        Log.e(TAG,"登录取消");
                    }
                });
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onError(UiError uiError) {
            Toast.makeText(SecondActivity.this, "授权失败", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onCancel() {
            Toast.makeText(SecondActivity.this, "授权取消", Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * 在调用Login的Activity或者Fragment中重写onActivityResult方法
     * @param requestCode
     * @param resultCode
     * @param data
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(requestCode == Constants.REQUEST_LOGIN){
            Tencent.onActivityResultData(requestCode,resultCode,data,mIUiListener);
        }
        super.onActivityResult(requestCode, resultCode, data);
    }
}

十一. 主页面显示页:

package com.bwie.secondweek_moni.activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import com.bwie.secondweek_moni.R;
import com.bwie.secondweek_moni.fragment.List_Fragment;
import com.bwie.secondweek_moni.fragment.QQ_Fragment;
import java.util.ArrayList;
import java.util.List;
import butterknife.Bind;
import butterknife.ButterKnife;

public class ThirdActivity extends AppCompatActivity {
    @Bind(R.id.button_person)
    RadioButton buttonPerson;
    @Bind(R.id.button_list)
    RadioButton buttonList;
    @Bind(R.id.groups)
    RadioGroup groups;
    @Bind(R.id.second_viewPager)
    ViewPager secondViewPager;
    private List<Fragment> list;

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

        //定义集合添加数据
        list = new ArrayList<>();
        list.add(new QQ_Fragment());
        list.add(new List_Fragment());

        //加入此行代码可使当页数据一直有效显示,不会随着页面滑动而消失
        secondViewPager.setOffscreenPageLimit(list.size());

        //设置适配器
        secondViewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
            @Override
            public Fragment getItem(int position) {
                return list.get(position);
            }

            @Override
            public int getCount() {
                return list.size();
            }
        });

        //设置viewpager的滑动监听事件
        secondViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }

            @Override
            public void onPageSelected(int position) {
                groups.check(groups.getChildAt(position).getId());
            }

            @Override
            public void onPageScrollStateChanged(int state) {
            }
        });
        //设置button按钮的监听事件
        groups.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                switch (checkedId) {
                    case R.id.button_person:
                        secondViewPager.setCurrentItem(0, false);
                        break;
                    case R.id.button_list:
                        secondViewPager.setCurrentItem(1, false);
                        break;
                    default:
                        break;
                }
            }
        });
    }
}

11. 1  对应的 QQ 信息显示页fragment:

package com.bwie.secondweek_moni.fragment;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import com.bwie.secondweek_moni.MainActivity;
import com.bwie.secondweek_moni.R;
import com.bwie.secondweek_moni.util.ImageLoaderUtil;
import com.nostra13.universalimageloader.core.ImageLoader;

import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;
//个人中心页
public class QQ_Fragment extends Fragment {
    @Bind(R.id.headPhoto)
    ImageView headPhoto;
    @Bind(R.id.userName)
    TextView userName;
    @Bind(R.id.gener)
    TextView gener;
    @Bind(R.id.address)
    TextView address;
    @Bind(R.id.outLogin)
    Button outLogin;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.qq_fragment, container, false);
        ButterKnife.bind(this, view);
        return view;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        //获取传递信息
        Intent intent = getActivity().getIntent();
        String icon = intent.getStringExtra("headPhoto");
        String name = intent.getStringExtra("name");
        String sex = intent.getStringExtra("gender");

        //设置用户信息
        String addRess = intent.getStringExtra("address");
        ImageLoader.getInstance().displayImage(icon,headPhoto, ImageLoaderUtil.getDefaultOption());
        /*Glide.with(this).load(icon).into(headPhoto);*/
        userName.setText("      "+name);
        gener.setText("      "+sex);
        address.setText("      "+addRess);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        ButterKnife.unbind(this);
    }

    //退出登录到主页
    @OnClick(R.id.outLogin)
    public void onViewClicked() {
        startActivity(new Intent(getActivity(), MainActivity.class));
    }
}

11. 2  对应的列表数据显示页fragment:

package com.bwie.secondweek_moni.fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import com.bwie.secondweek_moni.R;
import com.bwie.secondweek_moni.adapter.DataAdapter;
import com.bwie.secondweek_moni.bean.DataBean;
import com.bwie.secondweek_moni.okhttp.AbstractUiCallBack;
import com.bwie.secondweek_moni.okhttp.OkhttpUtils;
import com.liaoinstan.springview.container.DefaultFooter;
import com.liaoinstan.springview.container.DefaultHeader;
import com.liaoinstan.springview.widget.SpringView;
import butterknife.Bind;
import butterknife.ButterKnife;

//列表页
public class List_Fragment extends Fragment {
    @Bind(R.id.recyclerView)
    RecyclerView recyclerView;
    @Bind(R.id.springView)
    SpringView springView;
    int page = 0;     //初始化为第0页数据

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.list_fragment, container, false);
        ButterKnife.bind(this, view);
        return view;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        //设置线性布局管理器,加载数据
        LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false);
        recyclerView.setLayoutManager(layoutManager);
        getData();

        //设置SpringView进行多条目加载的头布局和尾布局
        springView.setHeader(new DefaultHeader(getActivity()));
        springView.setFooter(new DefaultFooter(getActivity()));

        //设置SpringView的刷新监听事件
        springView.setListener(new SpringView.OnFreshListener() {
            @Override
            public void onRefresh() {       //上拉刷新显示数据更多
                page++;
                getData();
                springView.onFinishFreshAndLoad();
            }

            @Override
            public void onLoadmore() {      //下拉加载初始化页数据
                page = 0;
                getData();
                springView.onFinishFreshAndLoad();
            }
        });
    }

    public void getData(){
        String path = "http://tingapi.ting.baidu.com/v1/restserver/ting?method=baidu.ting.billboard.billList&type=1&size=10&offset="+page;
        OkhttpUtils.getInstance().asy(null, path, new AbstractUiCallBack<DataBean>() {
            @Override
            public void success(DataBean dataBean) {
                //获取数据 .调用适配器中的添加数据的方法,,刷新添加到前面
                DataAdapter adapter = new DataAdapter(getActivity());
                adapter.addData(dataBean.getSong_list());
                recyclerView.setAdapter(adapter);
            }

            @Override
            public void failure(Exception e) {
                Toast.makeText(getActivity(),"数据错误"+e,Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        ButterKnife.unbind(this);
    }
}
11. 3 显示列表信息的适配器类:

package com.bwie.secondweek_moni.adapter;
import android.content.Context;
import android.content.Intent;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.bwie.secondweek_moni.R;
import com.bwie.secondweek_moni.activity.FourthActivity;
import com.bwie.secondweek_moni.bean.DataBean;
import com.bwie.secondweek_moni.util.ImageLoaderUtil;
import com.nostra13.universalimageloader.core.ImageLoader;
import java.util.ArrayList;
import java.util.List;
import butterknife.Bind;
import butterknife.ButterKnife;

//自定义适配器类
public class DataAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private Context context;
    private List<DataBean.SongListBean> list;

    public DataAdapter(Context context) {
        this.context = context;
    }

    //声明数据来源,添加数据
    public void addData(List<DataBean.SongListBean> songList) {
        if (this.list == null) {
            this.list = new ArrayList<>();
        }
        this.list.addAll(songList);
        notifyDataSetChanged();
    }

    //创建条目布局
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.item, null);
        return new ItemViewHolder(view);
    }

    //绑定数据
    @Override
    public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
        //设置条目信息
        final ItemViewHolder viewHolder = (ItemViewHolder) holder;
        viewHolder.text01.setText("歌曲: " + list.get(position).getTitle());
        viewHolder.text02.setText("歌手: " + list.get(position).getAuthor());
        ImageLoader.getInstance().displayImage(list.get(position).getPic_premium(), viewHolder.image, ImageLoaderUtil.getDefaultOption());

        //添加RecyclerView的单击事件,点击RecyclerView控件后把对应条目的标题传到详情Activity并显示(详情页效果图未提供,里面就一个TextView,接收到数据后,给TextView设置值即可)
        ((ItemViewHolder) holder).text01.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(context, FourthActivity.class);
                intent.putExtra("title",list.get(position).getTitle());
                context.startActivity(intent);
            }
        });

        //添加RecyclerView的长按事件,长按删除该条目
        ((ItemViewHolder) holder).text02.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                list.remove(position);
                Toast.makeText(context,"长按删除当前条目",Toast.LENGTH_SHORT).show();
                notifyDataSetChanged();
                return false;
            }
        });
    }

    @Override
    public int getItemCount() {
        return list.size();
    }

    static class ItemViewHolder extends RecyclerView.ViewHolder {
        @Bind(R.id.image)
        ImageView image;
        @Bind(R.id.text01)
        TextView text01;
        @Bind(R.id.text02)
        TextView text02;

        ItemViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
        }
    }
}

十二. 跳转显示数据的Activity页

package com.bwie.secondweek_moni.activity;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import com.bwie.secondweek_moni.R;
import butterknife.Bind;
import butterknife.ButterKnife;
//TextView详情页
public class FourthActivity extends AppCompatActivity {
    @Bind(R.id.text)
    TextView text;

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

        String title = getIntent().getStringExtra("title");
        text.setText("歌曲:"+title);
    }
}

十三. 页面布局

1. color文件夹中显示字体颜色的color.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 被选中的按钮,文本显示成红色,其他显示成黑色 -->
    <item android:state_checked="true" android:color="@color/selected"></item>
    <item android:state_checked="false" android:color="@color/defaulted"></item>
</selector>
在对应的values文件夹下的colors.xml布局文件中添加代码:

<!--字体颜色-->
<color name="selected">#FF0000</color>
<color name="defaulted">#000000</color>

2. MainActivity对应的activity_main.xml

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

    <android.support.v4.view.ViewPager
        android:id="@+id/main_viewPager"
        android:layout_above="@+id/groups"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></android.support.v4.view.ViewPager>

    <RadioGroup
        android:id="@+id/groups"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true">
        <RadioButton
            android:text="登录"
            android:padding="10dp"
            android:button="@null"
            android:checked="true"
            android:textSize="18sp"
            android:gravity="center"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:id="@+id/button_person"
            android:textColor="@color/color"
            android:layout_height="wrap_content" />

        <RadioButton
            android:text="注册"
            android:padding="10dp"
            android:button="@null"
            android:textSize="18sp"
            android:gravity="center"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:id="@+id/button_list"
            android:textColor="@color/color"
            android:layout_height="wrap_content" />
    </RadioGroup>
</RelativeLayout>

3. SecondActivity对应的activity_second.xml

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

    <Button
        android:text="点击登录QQ"
        android:onClick="qq_Second"
        android:background="#1E90FF"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"/>
</RelativeLayout>

4. ThirdActivity对应的activity_third.xml

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

    <android.support.v4.view.ViewPager
        android:id="@+id/second_viewPager"
        android:layout_above="@+id/groups"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></android.support.v4.view.ViewPager>

    <RadioGroup
        android:id="@+id/groups"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true">
        <RadioButton
            android:text="个人中心"
            android:padding="10dp"
            android:button="@null"
            android:checked="true"
            android:textSize="18sp"
            android:gravity="center"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:id="@+id/button_person"
            android:textColor="@color/color"
            android:layout_height="wrap_content" />

        <RadioButton
            android:text="列表"
            android:padding="10dp"
            android:button="@null"
            android:textSize="18sp"
            android:gravity="center"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:id="@+id/button_list"
            android:textColor="@color/color"
            android:layout_height="wrap_content" />
    </RadioGroup>
</RelativeLayout>

5. FourthActivity对应的activity_fourth.xml

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

    <TextView
        android:id="@+id/text"
        android:textSize="28sp"
        android:gravity="center"
        android:textColor="#3609ea"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"/>
</RelativeLayout>
6. 登录页面对应的login_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:background="@drawable/b"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RelativeLayout
        android:id="@+id/reative"
        android:background="#1e8ffe"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:padding="20dp"
            android:textSize="26sp"
            android:text="登录界面"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"    />
    </RelativeLayout>

    <EditText
        android:id="@+id/tel_Login"
        android:hint="请输入您的手机号"
        android:layout_marginTop="58dp"
        android:layout_below="@+id/reative"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"/>

    <EditText
        android:id="@+id/pwd_Login"
        android:hint="请输入您的密码"
        android:layout_marginTop="58dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/tel_Login"
        android:layout_centerHorizontal="true"/>

    <Button
        android:text="登录"
        android:textSize="21sp"
        android:id="@+id/login"
        android:background="#1E90FF"
        android:layout_width="188dp"
        android:layout_marginTop="108dp"
        android:layout_height="wrap_content"
        android:layout_below="@+id/pwd_Login"
        android:layout_centerHorizontal="true" />

    <Button
        android:textSize="21sp"
        android:id="@+id/qqLogin"
        android:text="第三方QQ登录"
        android:background="#1E90FF"
        android:layout_width="188dp"
        android:layout_marginBottom="108dp"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"  />
</RelativeLayout>

7. 注册页面对应的_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:background="@drawable/b"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RelativeLayout
        android:id="@+id/reative"
        android:background="#1e8ffe"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:padding="20dp"
            android:textSize="26sp"
            android:text="注册界面"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"    />
    </RelativeLayout>

    <EditText
        android:id="@+id/tel_Reg"
        android:hint="请输入您的手机号"
        android:layout_marginTop="58dp"
        android:layout_below="@+id/reative"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"/>

    <EditText
        android:id="@+id/pwd_Reg"
        android:hint="请输入您的密码"
        android:layout_marginTop="58dp"
        android:layout_below="@+id/tel_Reg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"/>

    <Button
        android:text="注册"
        android:id="@+id/reg"
        android:textSize="21sp"
        android:background="#1E90FF"
        android:layout_width="188dp"
        android:layout_marginTop="108dp"
        android:layout_below="@+id/pwd_Reg"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true" />

</RelativeLayout>

8. QQ登录信息页面对应的_fragment.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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"  >

    <RelativeLayout
        android:background="#1e8ffe"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:padding="20dp"
            android:textSize="26sp"
            android:text="个人中心"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"    />
    </RelativeLayout>

    <ImageView
        android:layout_gravity="center_horizontal"
        android:src="@mipmap/ic_launcher"
        android:layout_marginTop="58dp"
        android:layout_height="88dp"
        android:layout_width="88dp"
        android:id="@+id/headPhoto" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_marginTop="88dp"
        android:layout_height="50dp">
        <TextView
            android:layout_alignParentLeft="true"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="120dp"
            android:textSize="18sp"
            android:text="用户名:"/>
        <TextView
            android:layout_alignParentRight="true"
            android:layout_width="wrap_content"
            android:layout_marginRight="138dp"
            android:layout_height="50dp"
            android:id="@+id/userName"
            android:textSize="18sp"
            android:text="userName" />
    </RelativeLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="50dp">
        <TextView
            android:layout_alignParentLeft="true"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="120dp"
            android:textSize="18sp"
            android:text="性别" />
        <TextView
            android:layout_alignParentRight="true"
            android:layout_width="wrap_content"
            android:layout_marginRight="138dp"
            android:layout_height="50dp"
            android:id="@+id/gener"
            android:textSize="18sp"
            android:text="gener" />
    </RelativeLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="50dp">
        <TextView
            android:layout_alignParentLeft="true"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="120dp"
            android:textSize="18sp"
            android:text="地址:" />
        <TextView
            android:layout_alignParentRight="true"
            android:layout_width="wrap_content"
            android:layout_marginRight="138dp"
            android:layout_height="50dp"
            android:id="@+id/address"
            android:textSize="18sp"
            android:text="address" />
    </RelativeLayout>

    <Button
        android:text="退出登录"
        android:id="@+id/outLogin"
        android:layout_marginTop="88dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="@android:color/white"
        android:background="@android:color/holo_blue_light" />

</LinearLayout>


9. 列表页面对应的_fragment.xml

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

    <RelativeLayout
        android:background="#1e8ffe"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:padding="20dp"
            android:text="列表"
            android:textSize="26sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"    />
    </RelativeLayout>

    <com.liaoinstan.springview.widget.SpringView
        android:id="@+id/springView"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>
    </com.liaoinstan.springview.widget.SpringView>
</LinearLayout>

10. 列表数据适配器类对应的item.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"  >

    <ImageView
        android:id="@+id/image"
        android:layout_width="88dp"
        android:layout_height="88dp"
        android:src="@mipmap/ic_launcher" />

    <LinearLayout
        android:layout_toRightOf="@id/image"
        android:layout_alignParentRight="true"
        android:layout_width="match_parent"
        android:gravity="center_horizontal"
        android:orientation="vertical"
        android:layout_height="88dp" >

        <TextView
            android:id="@+id/text01"
            android:layout_marginTop="18dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <TextView
            android:id="@+id/text02"
            android:layout_marginBottom="10dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>

</RelativeLayout>
	
清单文件 AndroidManifest.xml

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

    <!-- QQ登录授权所需权限 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <application
        android:name=".util.BaseApplication"
        android:allowBackup="true"
        android:icon="@drawable/home_data"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".activity.SecondActivity" />

        <!-- 注册SDKActivity -->
        <activity
            android:name="com.tencent.tauth.AuthActivity"
            android:launchMode="singleTask"
            android:noHistory="true">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <data android:scheme="tencent1105602574" />
                <!-- 开放平台获取的APPID -->
            </intent-filter>
        </activity>
        <activity
            android:name="com.tencent.connect.common.AssistActivity"
            android:screenOrientation="portrait"
            android:theme="@android:style/Theme.Translucent.NoTitleBar" />
        <activity android:name=".activity.ThirdActivity" />
        <activity android:name=".activity.FourthActivity"></activity>
    </application>

</manifest>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的 MVP 框架,包含 Okhttp+Retrofit 网络封装,Base 基类的抽取以及 APPLocation 的代码: 1. 首先创建一个 BaseView 接口,定义一些公共的 UI 操作方法: ```java public interface BaseView { void showLoading(); void hideLoading(); void showError(String error); } ``` 2. 接着创建一个 BasePresenter 类,定义一些公共的 Presenter 操作方法: ```java public class BasePresenter<V extends BaseView> { private WeakReference<V> mViewRef; public void attachView(V view) { mViewRef = new WeakReference<>(view); } public void detachView() { if (mViewRef != null) { mViewRef.clear(); mViewRef = null; } } public boolean isViewAttached() { return mViewRef != null && mViewRef.get() != null; } public V getView() { return mViewRef.get(); } public void checkViewAttached() { if (!isViewAttached()) throw new RuntimeException("Please call attachView() before requesting data to the Presenter"); } } ``` 3. 创建一个 BaseActivity 类,作为所有 Activity 的基类,包含一些公共的操作: ```java public abstract class BaseActivity<P extends BasePresenter> extends AppCompatActivity implements BaseView { protected P mPresenter; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(getLayoutId()); mPresenter = createPresenter(); if (mPresenter != null) { mPresenter.attachView(this); } initView(); } @Override protected void onDestroy() { super.onDestroy(); if (mPresenter != null) { mPresenter.detachView(); } } protected abstract int getLayoutId(); protected abstract P createPresenter(); protected abstract void initView(); } ``` 4. 接着创建一个 BaseFragment 类,作为所有 Fragment 的基类,也包含一些公共的操作: ```java public abstract class BaseFragment<P extends BasePresenter> extends Fragment implements BaseView { protected P mPresenter; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); mPresenter = createPresenter(); if (mPresenter != null) { mPresenter.attachView(this); } } @Override public void onDestroy() { super.onDestroy(); if (mPresenter != null) { mPresenter.detachView(); } } protected abstract P createPresenter(); } ``` 5. 创建一个 AppApplication 类,作为整个应用程序的入口,包含一些公共的配置信息和初始化操作: ```java public class AppApplication extends Application { private static AppApplication sInstance; @Override public void onCreate() { super.onCreate(); sInstance = this; // 初始化网络请求 RetrofitClient.getInstance().init(this); } public static AppApplication getInstance() { return sInstance; } } ``` 6. 创建一个 RetrofitClient 类,用于封装 Okhttp+Retrofit 网络请求: ```java public class RetrofitClient { private static final String TAG = "RetrofitClient"; private static final int DEFAULT_TIMEOUT = 30; private Retrofit mRetrofit = null; private OkHttpClient mOkHttpClient = null; private RetrofitClient() {} public static RetrofitClient getInstance() { return SingletonHolder.INSTANCE; } private static class SingletonHolder { private static final RetrofitClient INSTANCE = new RetrofitClient(); } public void init(Context context) { HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(); loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); mOkHttpClient = new OkHttpClient.Builder() .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) .readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) .writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) .addInterceptor(loggingInterceptor) .addInterceptor(new TokenInterceptor()) .build(); mRetrofit = new Retrofit.Builder() .baseUrl(ApiService.BASE_URL) .client(mOkHttpClient) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build(); } public ApiService getApiService() { return mRetrofit.create(ApiService.class); } } ``` 7. 创建一个 ApiService 接口,定义所有的网络请求接口: ```java public interface ApiService { String BASE_URL = "https://www.example.com/"; @POST("login") Observable<BaseResponse<User>> login(@Query("username") String username, @Query("password") String password); } ``` 8. 最后,我们可以创建一个 LoginPresenter 类,来处理登录相关的业务逻辑: ```java public class LoginPresenter extends BasePresenter<LoginContract.View> implements LoginContract.Presenter { private ApiService mApiService; public LoginPresenter() { mApiService = RetrofitClient.getInstance().getApiService(); } @Override public void login(String username, String password) { checkViewAttached(); getView().showLoading(); mApiService.login(username, password) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<BaseResponse<User>>() { @Override public void onSubscribe(Disposable d) { } @Override public void onNext(BaseResponse<User> userBaseResponse) { getView().hideLoading(); if (userBaseResponse.getCode() == 0) { getView().loginSuccess(userBaseResponse.getData()); } else { getView().showError(userBaseResponse.getMsg()); } } @Override public void onError(Throwable e) { getView().hideLoading(); getView().showError(e.getMessage()); } @Override public void onComplete() { } }); } } ``` 以上就是一个简单的 MVP 框架的实现,您可以根据自己的需求进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值