MVP+Recycleview實現輪播圖實現京東秒殺效果
MVP+Recycleview實現輪播圖,京東秒殺
2018年12月02日 19:55:26 遷就 閱讀數:830
1:先看看效果
2:build.gradle中匯入依賴
//依賴
implementation ‘com.jakewharton:butterknife:8.8.1’
annotationProcessor ‘com.jakewharton:butterknife-compiler:8.8.1’
implementation ‘com.google.code.gson:gson:2.8.5’
compile ‘com.squareup.okhttp3:okhttp:3.4.2’
implementation ‘com.facebook.fresco:fresco:0.14.1’
compile ‘com.nostra13.universalimageloader:universal-image-loader:1.9.5’
compile ‘com.android.support:recyclerview-v7:27.1.1’
implementation ‘com.github.bumptech.glide:glide:4.8.0’
annotationProcessor ‘com.github.bumptech.glide:compiler:4.8.0’
3:AndroidManifest.xml清單檔案中加入許可權
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
- 1
- 2
- 3
- 4
4:主佈局
程式碼:
<?xml version="1.0" encoding="utf-8"?>
<!--輪播圖的RecyclerView佈局--> <android.support.v7.widget.RecyclerView android:id="@+id/img_rcv" android:layout_width="match_parent" android:layout_height="300px"> </android.support.v7.widget.RecyclerView> <!--倒計時佈局--> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="京東秒殺" android:textSize="28px" android:textColor="#FF0000" android:textStyle="bold"/> <TextView android:id="@+id/tv_item" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="30px" android:text="秒殺剩餘時間5s" /> </LinearLayout> <!--秒殺的RecyclerView佈局--> <android.support.v7.widget.RecyclerView android:id="@+id/my_rcv" android:layout_width="match_parent" android:layout_height="match_parent" ></android.support.v7.widget.RecyclerView>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
分包:
5.建立MVP框架實現
5.0:請求資料介面
:http://result.eolinker.com/umIPmfS6c83237d9c70c7c9510c9b0f97171a308d13b611?uri=homepage
5.1:建立bean類:
5.2:OkHttpUtils工具類
public class OkHttpUtils {
//單例模式,把構造方法進行私有化
//
private OkHttpUtils(){};
static OkHttpClient client;
public static OkHttpClient getInstance(){
if (client==null) {
- 1
- 2
- 3
//更加安全
synchronized (OkHttpUtils.class) {
//快取的地方 mnt/sdcard
File file = new File(Environment.getExternalStorageDirectory(), “cache11”);
client = new OkHttpClient().newBuilder()
.readTimeout(3000, TimeUnit.SECONDS) //設定讀取超時時間
.connectTimeout(3000, TimeUnit.SECONDS) //設定連線的超時時間
.cache(new Cache(file, 10 * 1024))
.build();
}
}
return client;
}
/**
* get請求
* Callback 是一個介面
*/
public static void doGet(String url, Callback callback){
//1:拿到okhttpclient 對像
OkHttpClient client = getInstance();
//2:進行請求的操作
Request request = new Request.Builder()
.url(url)
.build();
client.newCall(request).enqueue(callback);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
//post請求
/**
*
* @param url 請求的地址
* @param parms 請求的引數
* @param callback callback
*/
public static void doPost(String url, Map<String,String> parms, Callback callback){
//得到客戶端的對像
OkHttpClient client = getInstance();
//不是FormBody,而是一個Builder
FormBody.Builder body = new FormBody.Builder();
//key value
for (String key:parms.keySet()){
//value的值
body.add(key,parms.get(key));
}
Request request = new Request.Builder()
.url(url)
.post(body.build())
.build();
client.newCall(request).enqueue(callback);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
//用來上傳圖片的
//url , 圖片 ,引數 Callback
public static void upImage(String url,File file,String filenName,Map<String,String> params,Callback callback){
OkHttpClient client = getInstance();
//requestBody的實現類 Formbody
MultipartBody.Builder builder = new MultipartBody.Builder();
if (params!=null){
for (String key :params.keySet()){
builder.addFormDataPart(key,params.get(key));
}
}
//設定型別
builder.setType(MultipartBody.FORM);
builder.addFormDataPart("file",filenName, RequestBody.create(MediaType.parse("application/octet-stream"),file));
// builder.setType(MultipartBody.FORM);
// builder.addFormDataPart("file",filenName,RequestBody.create(MediaType.parse("application/octet-stream"),file));
//builder.addFormDataPart("file","aa.png",builder.build());
Request request = new Request.Builder()
.url(url)
.post(builder.build())
.build();
client.newCall(request).enqueue(callback);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
}
5.3:model層
1:
public interface DataModel {
//請求資料的方法
void getData(String url, DataPresenter presenter);
}
2:
public class MyDataModel implements DataModel {
//請求資料的方法
@Override
public void getData(String url, final DataPresenter presenter) {
OkHttpUtils.doGet(url, new Callback() {
@Override
public void onFailure(Call call, IOException e) {}
@Override
public void onResponse(Call call, Response response) throws IOException {
//接收返回的資料
String json = response.body().string();
//進行解析 得到集合
Gson gson = new Gson();
Shop myDataBean = gson.fromJson(json, Shop.class);
Shop.DataBean data = myDataBean.getData();
//呼叫P層方法將資料傳給P層
presenter.Success(data);
}
});
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
}
view層
public interface DataView {
//接收資料的方法
void toBackHome(Shop.DataBean data);
}
presenter層
1:
public interface DataPresenter {
//成功與失敗的方法
void Success(Shop.DataBean data);
void Error();
}
2:
public class MyDataPresenter implements DataPresenter {
DataView dataView;
private final MyDataModel myDataModel;
public MyDataPresenter(DataView dataView) {
this.dataView=dataView;
myDataModel = new MyDataModel();
}
//成功
@Override
public void Success(Shop.DataBean data) {
dataView.toBackHome(data);
}
//失敗
@Override
public void Error() {}
public void netWork(String url){
myDataModel.getData(url,this);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
}
application類
public class App extends Application{
@Override
public void onCreate() {
super.onCreate();
//初始化Fresco使用預設配置
Fresco.initialize(this);
}
- 1
- 2
- 3
}
實現輪播圖的介面卡
1:佈局SimpleDraweeView控制元件實現:
<?xml version="1.0" encoding="utf-8"?>
<!--輪播圖的圖片控制元件-->
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/item_sdv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop">
</com.facebook.drawee.view.SimpleDraweeView>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
2:adapter中
public class ImgAdapter extends RecyclerView.Adapter{
Context context;
List<Shop.DataBean.Ad1Bean> list;
public ImgAdapter(Context context, List<Shop.DataBean.Ad1Bean> list) {
this.context=context;
this.list=list;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//引入輪播圖佈局
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.img_item,parent,false);
return new MyViewHolder(view);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
MyViewHolder myViewHolder = (MyViewHolder) holder;
//為輪播圖賦圖片
myViewHolder.item_sdv.setImageURI(list.get(position%list.size()).getImage());
}
@Override
public int getItemCount() {
return Integer.MAX_VALUE;
}
class MyViewHolder extends RecyclerView.ViewHolder{
private final SimpleDraweeView item_sdv;
public MyViewHolder(View view) {
super(view);
//找到佈局檔案中的ID
item_sdv = view.findViewById(R.id.item_sdv);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
}
京東秒殺介面卡:
1:佈局SimpleDraweeView+textview實現
<?xml version="1.0" encoding="utf-8"?>
<!--秒殺圖的圖片控制元件-->
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/rcv_sdv"
android:layout_width="200px"
android:layout_height="200px"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
fresco:actualImageScaleType="centerCrop"
fresco:placeholderImageScaleType="centerCrop"
fresco:roundAsCircle="true"
fresco:placeholderImage="@drawable/ic_launcher_background" />
<!--秒殺顯示價格的控制元件-->
<TextView
android:id="@+id/rcv_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10px"
android:layout_marginLeft="30px"
android:layout_marginTop="20px"
android:textColor="#FF0000"
android:text="¥49.90"/>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
2:adapter中
public class MsAdapter extends RecyclerView.Adapter{
Context context;
List<Shop.DataBean.DefaultGoodsListBean> list;
public MsAdapter(Context context, List<Shop.DataBean.DefaultGoodsListBean> list) {
this.context=context;
this.list=list;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//引入秒殺佈局檔案
View view = View.inflate(context, R.layout.ms_item, null);
MyViewHolder myViewHolder = new MyViewHolder(view);
return myViewHolder;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
MyViewHolder myViewHolder = (MyViewHolder) holder;
//為秒殺賦值
myViewHolder.rcv_tv.setText("¥"+list.get(position).getShop_price());
myViewHolder.rcv_sdv.setImageURI(list.get(position).getGoods_img());
}
@Override
public int getItemCount() {
return list.size();
}
class MyViewHolder extends RecyclerView.ViewHolder{
private final SimpleDraweeView rcv_sdv;
private final TextView rcv_tv;
public MyViewHolder(View view) {
super(view);
//找到秒殺佈局中的控制元件ID
rcv_sdv = view.findViewById(R.id.rcv_sdv);
rcv_tv = view.findViewById(R.id.rcv_tv);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
}
最後一個Actvity中
public class MainActivity extends Activity implements DataView {
String url = “http://result.eolinker.com/umIPmfS6c83237d9c70c7c9510c9b0f97171a308d13b611?uri=homepage”;
private List<Shop.DataBean.Ad1Bean> imglist;
private int item=5;
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//接收資料
Shop.DataBean data = (Shop.DataBean) msg.obj;
//設定輪播圖 進入輪播圖介面卡
imglist = data.getAd1();
ImgAdapter imgAdapter = new ImgAdapter(MainActivity.this, imglist);
final LinearLayoutManager layoutManager = new LinearLayoutManager(MainActivity.this, LinearLayoutManager.HORIZONTAL, false);
imgRcv.setLayoutManager(layoutManager);
imgRcv.setHasFixedSize(true);
imgRcv.setAdapter(imgAdapter);
PagerSnapHelper snapHelper = new PagerSnapHelper();
snapHelper.attachToRecyclerView(imgRcv);
imgRcv.scrollToPosition(imglist.size() * 10);
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
imgRcv.smoothScrollToPosition(layoutManager.findFirstVisibleItemPosition() + 1);
}
}, 2000, 2000, TimeUnit.MILLISECONDS);
//設定秒殺,進入秒殺介面卡
List<Shop.DataBean.DefaultGoodsListBean> defaultGoodsList = data.getDefaultGoodsList();
MsAdapter adapter = new MsAdapter(MainActivity.this, defaultGoodsList);
myRcv.setAdapter(adapter);
}
};
Handler handler2 = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(msg.what==0){
item--;
tvItem.setText("秒殺剩餘時間"+item+"s");
handler2.sendEmptyMessageDelayed(0,1000);
}
if(item==0){
//實現頁面跳轉
//這裡的跳轉actvity是京東秒殺倒計時跳轉的頁面,沒有什麼東西,建立一個actvity就好
Intent intent = new Intent(MainActivity.this,MsActivity.class);
startActivity(intent);
finish();
}
}
};
@BindView(R.id.my_rcv)
RecyclerView myRcv;
@BindView(R.id.img_rcv)
RecyclerView imgRcv;
@BindView(R.id.tv_item)
TextView tvItem;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
//例項化P層
MyDataPresenter myDataPresenter = new MyDataPresenter(this);
myDataPresenter.netWork(url);
//設定管理器
myRcv.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.HORIZONTAL, false));
//設定倒計時跳轉頁面
handler2.sendEmptyMessageDelayed(0,1000);
}
//接收資料的方法
@Override
public void toBackHome(Shop.DataBean data) {
Message msg = new Message();
msg.obj = data;
handler.sendMessage(msg);
}