Android轮播

此为课堂笔记!!!

用的是banner
GitHub地址

国际惯例先上图:
在这里插入图片描述

使用步骤:

Step1:

1.在build.gradle(Module:app)里引入依赖:implementation ‘com.youth.banner:banner:2.0.1’

2.在build.gradle(Module:app)的android控件里添加支持java8,记得点击右上角的Sync Now同步

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

Step2:写一个适配器:

1.准备工作:
ps:因为用到 RecyclerView 和 Glide ,所以需要引入依赖:
//recyclerview 列表
implementation ‘androidx.recyclerview:recyclerview:1.1.0’

//glide 图片加载
implementation ‘com.github.bumptech.glide:glide:4.11.0’
annotationProcessor ‘com.github.bumptech.glide:compiler:4.11.0’

2.正式代码:

    //Step2: 继承BannerAdapter后并实现BannerViewHolder和onBindView方法,并需要构造器
    //ps:BannerBean 是一个bean,有存放图片名称的属性,用来拼接请求服务器图片的路径,自行建一个bean存放图片路径
public class ImageAdapter extends BannerAdapter<BannerBean,ImageAdapter.BannerViewHolder> {


    private Context context;
    public ImageAdapter(List<BannerBean> datas , Context context) {
        super(datas);
        this.context=context;
    }

    /*创建ViewHolder,可以用viewType这个字段来区分不同的ViewHolder*/
    @Override
    public BannerViewHolder onCreateHolder(ViewGroup parent, int viewType) {
        ImageView imageView =new ImageView(parent.getContext());
        //注意,必须设置为match_parent,这个是viewpager2强制要求的
        imageView.setLayoutParams(new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT
        ));
        imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
        return new BannerViewHolder(imageView);
    }

    /*绑定数据*/
    @Override
    public void onBindView(BannerViewHolder holder, BannerBean data, int position, int size) {

        //这是请求服务端图片的路径,返回的是图片流
        String strImagePath = ServiceUrls.getMainPageMethodUrl("getBannerPicture") + "?pictureName=" + data.getBannerPicture();

        //用Glide请求加载图片,
        Glide.with(context)
                .load(strImagePath)
                .into(holder.imageView);

    }

    //Step1
    class BannerViewHolder extends RecyclerView.ViewHolder{
        ImageView imageView;

        public BannerViewHolder(@NonNull ImageView view) {
            super(view);
            this.imageView=view;
        }
    }
}

Step3:在需要轮播的布局文件中添加Banner:

    <com.youth.banner.Banner
        android:id="@+id/banner_home_header"
        android:layout_width="match_parent"
        android:layout_height="240dp" />

Step4:Banner具体方法的调用:

1.准备工作:

ps:因为这里用到了网络请求 和 其工具,还有 fastjson,所以需要引入以下:
引入依赖:
//==网络请求 需要设置网络权限
implementation ‘com.squareup.okhttp3:okhttp:4.4.0’//网络请求
implementation ‘com.squareup.okhttp3:logging-interceptor:4.4.0’//发送网络请求和返回数据的相关日志

//fastjson
implementation ‘com.alibaba:fastjson:1.2.68’

设置开启联网权限:在AndroidManifest.xml里的manufest里添加子控件,代码如下:

<!--添加时是此处代码:允许程序打开网络套接字-->
<uses-permission android:name="android.permission.INTERNET" />

用到的工具类(老师的):该工具类是请求服务器的方法,若自己有,则不需要:

package com.gx.banner;

import android.util.Log;

import androidx.annotation.NonNull;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.logging.HttpLoggingInterceptor;

/**
 * create by qzlysxj
 * Fix bu qzlysxj on 2020-2-26
 * <p>
 * 便于使用okhttp3的工具类
 */
public class OkHttpTool {
    //日志标志
    private static String TAG = "OkHttpTool";
    //OkHttpClient类
    private static final OkHttpClient myOkHttpClient;

    static {
        //========日志拦截器=========
        //Log拦截器
        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
            @Override
            public void log(@NonNull String message) {
                Log.i(TAG, message);
            }
        });
        //设置日志显示级别
        HttpLoggingInterceptor.Level level = HttpLoggingInterceptor.Level.BODY;
        loggingInterceptor.setLevel(level);

        //========cookie处理--让服务端记住app
        //这里是设置cookie的,但是并没有做持久化处理;只是把cookie保存在内存中
        CookieJar cookieJar=new CookieJar() {
            private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();
            //保存cookie
            @Override
            public void saveFromResponse(@NonNull HttpUrl url, @NonNull List<Cookie> cookies) {
                cookieStore.put(url.host(), cookies);
            }
            //获取cookie
            @Override
            public List<Cookie> loadForRequest(@NonNull HttpUrl url) {
                List<Cookie> cookies = cookieStore.get(url.host());
                return cookies != null ? cookies : new ArrayList<Cookie>();
            }
        };

        //创建OkHttpClient
        myOkHttpClient = new OkHttpClient.Builder()
                .connectTimeout(30, TimeUnit.SECONDS)//连接超时
                .writeTimeout(60, TimeUnit.SECONDS)//写入超时
                .readTimeout(60, TimeUnit.SECONDS)//读取超时
                .addInterceptor(loggingInterceptor)//添加日志处理拦截器
                .cookieJar(cookieJar)
                .build();
    }

    //================对外方法=====================

    /**
     * Get 请求
     * @param url{String} 请求地址
     * @param parameters{Map<String, Object>} 请求参数
     * @param responseCallback{ResponseCallback} 请求回调
     */
    @SuppressWarnings("unused")
    public static void httpGet(String url, Map<String, Object> parameters, ResponseCallback responseCallback) {
        Request request = createGetRequest(url, parameters);
        doRequest(request, responseCallback);
    }

    /**
     * POST 请求
     * @param url{String} 请求地址
     * @param parameters{Map<String, Object>} 请求参数
     * @param responseCallback{ResponseCallback} 请求回调
     */
    public static void httpPost(String url, Map<String, Object> parameters, ResponseCallback responseCallback) {
        Request request = createPostRequest(url, parameters);
        doRequest(request, responseCallback);
    }

    /**
     * POST 请求 JSON格式参数
     * @param url{String} 请求地址
     * @param json{String} JSON格式参数
     * @param responseCallback{ResponseCallback} 请求回调
     */
    @SuppressWarnings("unused")
    public static void httpPostJson(String url, String json, ResponseCallback responseCallback) {
        Request request = createPostRequestJson(url, json);
        doRequest(request, responseCallback);
    }

    /**
     * POST 请求 文件上传
     * @param url{String} 请求地址
     * @param parameters{Map<String, Object>} 请求参数
     * @param files{Map<String, File>} 上传的文件列表
     * @param responseCallback{ResponseCallback} 请求回调
     */
    @SuppressWarnings("unused")
    public static void httpPostWithFile(String url, Map<String, Object> parameters, Map<String, File> files, ResponseCallback responseCallback) {
        Request request = createPostRequestWithFile(url, parameters, files);
        doRequest(request, responseCallback);
    }

    /**
     * POST 请求 文件上传 byte数组
     * @param url{String} 请求地址
     * @param parameters{Map<String, Object>} 请求参数
     * @param files{Map<String, byte[]>}上传的文件列表
     * @param responseCallback{ResponseCallback} 请求回调
     */
    @SuppressWarnings("unused")
    public static void httpPostWithFileByte(String url, Map<String, Object> parameters, Map<String, byte[]> files, ResponseCallback responseCallback) {
        Request request = createPostRequestWithFileByte(url, parameters, files);
        doRequest(request, responseCallback);
    }


    //=====回调接口======
    public interface ResponseCallback {
        void onResponse(boolean isSuccess, int responseCode, String response, Exception exception);
    }


    //===========私有方法===============
    //====构建请求====

    //构建 Get请求
    private static Request createGetRequest(String url, Map<String, Object> parameters) {
        StringBuilder urlBuilder = new StringBuilder();
        urlBuilder.append(url);
        if (url.indexOf('?') <= -1) {
            //未拼接参数
            urlBuilder.append("?");
        }

        for (Map.Entry<String, Object> entry : parameters.entrySet()) {
            urlBuilder.append("&");
            urlBuilder.append(entry.getKey());
            urlBuilder.append("=");
            urlBuilder.append(entry.getValue().toString());
        }
        return getBaseRequest().url(urlBuilder.toString()).build();
    }

    //构建 POST 请求
    private static Request createPostRequest(String url, Map<String, Object> parameters) {
        @SuppressWarnings("all")
        FormBody.Builder builder = new FormBody.Builder(Charset.forName("UTF-8"));
        if (parameters != null) {
            for (Map.Entry<String, Object> entry : parameters.entrySet()) {
                builder.add(entry.getKey(), entry.getValue().toString());
            }
        }
        FormBody formBody = builder.build();
        return getBaseRequest().url(url).post(formBody).build();
    }

    //构建 POST JSON格式参数请求
    private static Request createPostRequestJson(String url, String json) {
        MediaType mediaType = MediaType.parse("application/json;charset=utf-8");
        RequestBody body = RequestBody.create(json,mediaType);
        return getBaseRequest().url(url).post(body).build();
    }

    //构建 POST带文件的 请求
    private static Request createPostRequestWithFile(String url, Map<String, Object> parameters, Map<String, File> files) {
        // form 表单形式上传
        MultipartBody.Builder requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM);
        if (files != null) {
            for (Map.Entry<String, File> fileEntry : files.entrySet()) {
                File file = fileEntry.getValue();
                if (file != null) {
                    // MediaType.parse() 里面是上传的文件类型。
                    RequestBody body = RequestBody.create(file,MediaType.parse("application/octet-stream"));
                    String filename = file.getName();
                    // 参数分别为, 请求key ,文件名称 , RequestBody
                    requestBody.addFormDataPart(fileEntry.getKey(), filename, body);
                }
            }
        }
        if (parameters != null) {
            // map 里面是请求中所需要的 key 和 value
            for (Map.Entry<String, Object> entry : parameters.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue().toString();
                requestBody.addFormDataPart(key, value);
            }
        }
        return getBaseRequest().url(url).post(requestBody.build()).build();
    }

    //构建 POST带文件的 请求
    private static Request createPostRequestWithFileByte(String url, Map<String, Object> parameters, Map<String, byte[]> files) {
        // form 表单形式上传
        MultipartBody.Builder requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM);
        if (files != null) {
            for (Map.Entry<String, byte[]> fileEntry : files.entrySet()) {
                byte[] file = fileEntry.getValue();
                if (file != null) {
                    // MediaType.parse() 里面是上传的文件类型。
                    RequestBody body = RequestBody.create(file,MediaType.parse("application/octet-stream"));
                    // 参数分别为, 请求key ,文件名称 , RequestBody
                    requestBody.addFormDataPart(fileEntry.getKey(), fileEntry.getKey(), body);
                }
            }
        }
        if (parameters != null) {
            // map 里面是请求中所需要的 key 和 value
            for (Map.Entry<String, Object> entry : parameters.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue().toString();
                requestBody.addFormDataPart(key, value);
            }
        }
        return getBaseRequest().url(url).post(requestBody.build()).build();
    }

    //===实际进行请求的方法
    private static void doRequest(final Request request, final ResponseCallback responseCallback) {
        //使用okhttp3的异步请求
        myOkHttpClient.newCall(request).enqueue(new Callback() {
            //失败回调
            @Override
            public void onFailure(@NonNull Call call, @NonNull IOException e) {
                //回调
                responseCallback.onResponse(false, -1, null, e);
                //用于输出错误调试信息
                if (e.getMessage()!=null){
                    Log.e(TAG, e.getMessage());
                }
            }
            //成功回调
            @Override
            public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                int responseCode = response.code();//获取响应码
                ResponseBody responseBody = response.body();//获取 ResponseBody
                if (response.isSuccessful() && responseBody != null) {
                    String strResponse = responseBody.string();
                    //回调
                    responseCallback.onResponse(true, responseCode, strResponse, null);
                } else {
                    //回调
                    responseCallback.onResponse(false, responseCode, null, null);
                }
            }
        });
    }

    //获取请求 指定client为Android
    private static Request.Builder getBaseRequest() {
        Request.Builder builder = new Request.Builder();
        builder.addHeader("client", "Android");
        return builder;
    }
}


//.addInterceptor(new Interceptor() {
//    @Override
//    public Response intercept(@NonNull Chain chain) throws IOException {
//        Request request = chain.request().newBuilder()
//            .addHeader("Connection", "close").build();
//        return chain.proceed(request);
//    }
//})


/*以前自己写的日志拦截器*/
//添加日志处理拦截器
//.addInterceptor(new Interceptor() {
//    @Override
//    public Response intercept(@NonNull Chain chain) throws IOException {
//        Request request = chain.request();
//        long startTime = System.currentTimeMillis();
//        Response response = chain.proceed(chain.request());
//        long endTime = System.currentTimeMillis();
//        long duration = endTime - startTime;
//        MediaType mediaType = response.body().contentType();
//        String content = response.body().string();
//        Log.d(TAG, "\n");
//        Log.d(TAG, "----------Start----------------");
//        Log.d(TAG, "| " + request.toString());
//        String method = request.method();
//        if ("POST".equals(method)) {
//            StringBuilder sb = new StringBuilder();
//            if (request.body() instanceof FormBody) {
//                FormBody body = (FormBody) request.body();
//                for (int i = 0; i < body.size(); i++) {
//                    sb.append(body.encodedName(i) + "=" + body.encodedValue(i) + ",");
//                }
//                if (sb.length() > 0) {
//                    //在参数不为空的情况下处理最后的 “,”
//                    sb.delete(sb.length() - 1, sb.length());
//                }
//                Log.d(TAG, "| RequestParams:{" + sb.toString() + "}");
//            }
//        }
//        Log.d(TAG, "| Response:" + content);
//        Log.d(TAG, "----------End:" + duration + "毫秒----------");
//        //由于前面的代码已经获取了响应结果,会导致后续代码无法获取到响应结果
//        // 需要重新构建一个响应结果并返回
//        return response.newBuilder()
//                .body(ResponseBody.create(mediaType, content))
//                .build();
//    }
//})

2.正式代码:

public class MainActivity extends AppCompatActivity {
    private Banner banner;

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

        banner = findViewById(R.id.banner_home_header);//获取Banner控件

        initView();
    }

    private void initView() {

        //==获取服务端需要轮播的图片名称list集合数据
        String url= ServiceUrls.getMainPageMethodUrl("getBannerInfo");//请求路径
        OkHttpTool.httpPost(url, null, new OkHttpTool.ResponseCallback() {
            @Override
            public void onResponse(final boolean isSuccess, final int responseCode, final String response, Exception exception) {
                MainActivity.this.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if(isSuccess && responseCode==200){
                            List<BannerBean> bannerBeanList= JSON.parseObject(response,new TypeReference<List<BannerBean>>(){});

                            //****重点在这:显示轮播(前面的代码只是获取需要轮播的图片名称集合,准备数据)
                            banner.setAdapter(new ImageAdapter(bannerBeanList,MainActivity.this))
                                    .setIndicator(new CircleIndicator(MainActivity.this))//设置圆形指示器
                                    .setIndicatorSelectedColorRes(R.color.colorPrimary)//设置被选中的指示器的颜色
                                    .isAutoLoop(true)//自动开启轮播
                                    .setDelayTime(2*1000)//轮播间隔
                                    .setOnBannerListener(new OnBannerListener() {//图片点击事件
                                        @Override
                                        public void OnBannerClick(Object data, int position) {
                                            Toast.makeText(MainActivity.this,"点击了图片",Toast.LENGTH_SHORT).show();
                                        }
                                    });
                            banner.start();//开启轮播

                        }else{
                            Toast.makeText(MainActivity.this,"连接服务器失败",Toast.LENGTH_SHORT).show();
                        }
                    }
                });
            }
        });
        
    }
}

tip:因是Android P系统限制了明文流量的网络请求,所以必须做以下工作

1.在res层右键》New》Folder》XML Resources Folder》finis
2.res层就多了个xml层,然后新建network_security_config.xml放进xml层,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <!--开发中可以考虑使用-->
    <!--Android API 28 关闭HTTPS服务器监测-->
    <base-config cleartextTrafficPermitted="true" />

    <!--实际部署后只放开自己的服务端地址-->
    <!--只将本服务XXX.XXX.XXX.XXX器放开-->
<!--    <domain-config cleartextTrafficPermitted="true">-->
<!--        <domain includeSubdomains="true">XXX.XXX.XXX.XXX</domain>-->
<!--    </domain-config>-->
</network-security-config>

3.在AndroidManifest.xml添加 android:networkSecurityConfig="@xml/network_security_config"即可:

    <application
        android:networkSecurityConfig="@xml/network_security_config"

猜你喜欢

转载自blog.csdn.net/weixin_44619313/article/details/107618980
今日推荐