添加网络权限:
<uses-permission android:name="android.permission.INTERNET" />
在build.gradle中添加:
// greenDAO // 整个工程中的build.gradle中添加: classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2'
在项目下的build.gradle中添加:
// Glide compile 'com.github.bumptech.glide:glide:4.5.0' // Retrofit compile 'com.squareup.retrofit2:converter-gson:2.3.0' compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' // RxJava+Retrofit compile 'io.reactivex.rxjava2:rxjava:2.1.5' compile 'io.reactivex.rxjava2:rxandroid:2.0.1' // AVLoadingIndicatorView,相当于进度条,有丰富的正在加载中的动画 compile 'com.wang.avi:library:1.0.5' implementation 'com.android.support:recyclerview-v7:27.0.2' implementation 'com.android.support:appcompat-v7:27.0.2' // app模块下的build.gradle中添加: compile 'org.greenrobot:greendao:3.2.2'
布局文件activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <com.wang.avi.AVLoadingIndicatorView app:indicator_color="@color/colorAccent" android:layout_centerInParent="true" android:id="@+id/loading_view" app:indicator="Pacman" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" app:layoutManager="android.support.v7.widget.LinearLayoutManager" android:layout_width="match_parent" android:layout_height="match_parent"/> </RelativeLayout>
布局文件item_food.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="wrap_content"> <TextView android:id="@+id/title_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Button android:id="@+id/delete_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:background="#f00" android:text="删除" android:textColor="#fff" /> <ImageView android:id="@+id/pic_iv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/title_tv" /> </RelativeLayout>
全局代码文件activity文件夹下MainActivity.java
package com.estyle.day0127.activity; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.RecyclerView; import android.view.View; import com.estyle.day0127.R; import com.estyle.day0127.adapter.FoodAdaoter; import com.estyle.day0127.application.MyApplication; import com.estyle.day0127.bean.DataBean; import com.estyle.day0127.bean.DataBeanDao; import com.estyle.day0127.bean.FoodBean; import com.estyle.day0127.httpservice.FoodHttpService; import com.wang.avi.AVLoadingIndicatorView; import java.util.List; import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.functions.Consumer; import io.reactivex.functions.Function; import io.reactivex.schedulers.Schedulers; import retrofit2.Retrofit; import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; import retrofit2.converter.gson.GsonConverterFactory; /** * 下载过程中,展示数据之前,展示加载进度UI控件AVLoadingIndicatorView * 1、各种导包,各种布局 * 使用Retrofit + RxJava下载数据 * 数据在RecyclerView上展示文字,图片使用Glide(版本4,只能用在studio3上)框架加载,圆角 */ // http://www.qubaobei.com/ios/cf/dish_list.php?stage_id=1&limit=10&page=1 public class MainActivity extends AppCompatActivity { protected AVLoadingIndicatorView mLoadingView; protected RecyclerView mRecyclerView; private Retrofit mRetrofit; private FoodAdaoter mAdaoter; private DataBeanDao mDao; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.setContentView(R.layout.activity_main); // 初始化greenDAO mDao = MyApplication.getDaoSession() .getDataBeanDao(); initView(); loadData(); } private void loadData() { // 构建retrofit mRetrofit = new Retrofit.Builder() .baseUrl("http://www.qubaobei.com/") .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build(); // 获取接口实例,并获取其中的观察者 FoodHttpService httpService = mRetrofit.create(FoodHttpService.class); Observable<FoodBean> observable = httpService.getObservable(1); // 自动下载数据并设置数据源, 指定数据下载线程为子线程,数据变换 observable.subscribeOn(Schedulers.io()) .map(new Function<FoodBean, List<DataBean>>() { @Override public List<DataBean> apply(FoodBean foodBean) throws Exception { return foodBean.getData(); } }) // 换回主线程展示 .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Consumer<List<DataBean>>() { @Override public void accept(List<DataBean> dataBeans) throws Exception { // 下载数据成功,存入数据库 for (DataBean data : dataBeans) { data.set_id(System.currentTimeMillis()); mDao.insert(data); } // 存储完毕后,从数据库读取数据 List<DataBean> datas = mDao.queryBuilder() .build() .list(); mAdaoter.addDatas(datas); // 成功展示数据后,隐藏正在加载进度视图 mLoadingView.setVisibility(View.GONE); } }); } private void initView() { mLoadingView = (AVLoadingIndicatorView) findViewById(R.id.loading_view); mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); // 适配器伴随RecyclerView诞生而诞生,直接绑定,等数据获取到了再展示 mAdaoter = new FoodAdaoter(this); mRecyclerView.setAdapter(mAdaoter); } }
全局代码文件adapter文件夹下FoodAdaoter.java
package com.estyle.day0127.adapter; import android.content.Context; import android.support.v7.widget.RecyclerView; 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 android.widget.Toast; import com.bumptech.glide.Glide; import com.bumptech.glide.load.resource.bitmap.RoundedCorners; import com.bumptech.glide.request.RequestOptions; import com.estyle.day0127.R; import com.estyle.day0127.application.MyApplication; import com.estyle.day0127.bean.DataBean; import com.estyle.day0127.bean.DataBeanDao; import java.util.ArrayList; import java.util.List; public class FoodAdaoter extends RecyclerView.Adapter<FoodAdaoter.ViewHolder> { private final DataBeanDao mDao; private Context mContext; private List<DataBean> mDatas; public FoodAdaoter(Context context) { mContext = context; mDatas = new ArrayList<>(); // 初始化Dao,用于删除数据 mDao = MyApplication.getDaoSession() .getDataBeanDao(); } // 添加数据 public void addDatas(List<DataBean> datas) { mDatas.addAll(datas); notifyDataSetChanged(); } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View itemView = LayoutInflater.from(mContext) .inflate(R.layout.item_food, parent, false); return new ViewHolder(itemView); } @Override public void onBindViewHolder(ViewHolder holder, final int position) { final DataBean data = mDatas.get(position); holder.mTitleTextView.setText(data.getTitle()); // 请求加载图片的配置项,可以扩展圆角,圆图等功能 // 注意:该配置项是Glide4版本独有的功能,需要studio3使用 RequestOptions options = new RequestOptions(); // 变换为圆角 options.transform(new RoundedCorners(200)); // 使用Glide框架展示图片 Glide.with(mContext) .load(data.getPic()) .apply(options)// 应用我们额外的配置项 .into(holder.mPicImageView); // 删除数据按钮点击监听 holder.mDeleteBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 删除数据库对应数据 mDao.delete(data); // 删除UI界面上item对应展示的数据并刷新 mDatas.remove(position); notifyDataSetChanged(); Toast.makeText(mContext, "成功删除第" + position + "条数据", Toast.LENGTH_SHORT).show(); } }); } @Override public int getItemCount() { return mDatas == null ? 0 : mDatas.size(); } static class ViewHolder extends RecyclerView.ViewHolder { Button mDeleteBtn; TextView mTitleTextView; ImageView mPicImageView; public ViewHolder(View itemView) { super(itemView); mDeleteBtn = itemView.findViewById(R.id.delete_btn); mTitleTextView = itemView.findViewById(R.id.title_tv); mPicImageView = itemView.findViewById(R.id.pic_iv); } } }
全局代码文件application文件夹下MyApplication.java
package com.estyle.day0127.application; import android.app.Application; import com.estyle.day0127.bean.DaoMaster; import com.estyle.day0127.bean.DaoSession; import org.greenrobot.greendao.database.Database; public class MyApplication extends Application { private static DaoSession sDaoSession; @Override public void onCreate() { super.onCreate(); initGreenDAO(); } private void initGreenDAO() { DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "food.db"); Database db = helper.getWritableDb(); sDaoSession = new DaoMaster(db).newSession(); } public static DaoSession getDaoSession() { return sDaoSession; } }
全局代码文件bean文件夹下DataBean.java
package com.estyle.day0127.bean; import org.greenrobot.greendao.annotation.Entity; import org.greenrobot.greendao.annotation.Id; import org.greenrobot.greendao.annotation.Generated; @Entity public class DataBean { /** * id : 8289 * title : 油焖大虾 * pic : http://www.qubaobei.com/ios/cf/uploadfile/132/9/8289.jpg * collect_num : 1653 * food_str : 大虾 葱 生姜 植物油 料酒 * num : 1653 */ @Id(autoincrement = true) private long _id; private String id; private String title; private String pic; private String collect_num; private String food_str; private int num; @Generated(hash = 1343076215) public DataBean(long _id, String id, String title, String pic, String collect_num, String food_str, int num) { this._id = _id; this.id = id; this.title = title; this.pic = pic; this.collect_num = collect_num; this.food_str = food_str; this.num = num; } @Generated(hash = 908697775) public DataBean() { } public long get_id() { return this._id; } public void set_id(long _id) { this._id = _id; } public String getId() { return this.id; } public void setId(String id) { this.id = id; } public String getTitle() { return this.title; } public void setTitle(String title) { this.title = title; } public String getPic() { return this.pic; } public void setPic(String pic) { this.pic = pic; } public String getCollect_num() { return this.collect_num; } public void setCollect_num(String collect_num) { this.collect_num = collect_num; } public String getFood_str() { return this.food_str; } public void setFood_str(String food_str) { this.food_str = food_str; } public int getNum() { return this.num; } public void setNum(int num) { this.num = num; } }
全局代码文件bean文件夹下FoodBean.java
package com.estyle.day0127.bean; import java.util.List; public class FoodBean { /** * ret : 1 * data : [{"id":"8289","title":"油焖大虾","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/9/8289.jpg","collect_num":"1653","food_str":"大虾 葱 生姜 植物油 料酒","num":1653},{"id":"2127","title":"四川回锅肉","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/3/2127.jpg","collect_num":"1585","food_str":"猪肉 青蒜 青椒 红椒 姜片","num":1585},{"id":"30630","title":"超简单芒果布丁","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/31/30630.jpg","collect_num":"1519","food_str":"QQ糖 牛奶 芒果","num":1519},{"id":"9073","title":"家常红烧鱼","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/10/9073.jpg","collect_num":"1416","food_str":"鲜鱼 姜 葱 蒜 花椒","num":1416},{"id":"10097","title":"家常煎豆腐","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/11/10097.jpg","collect_num":"1404","food_str":"豆腐 新鲜红椒 青椒 葱花 油","num":1404},{"id":"10509","title":"水煮肉片","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/11/10509.jpg","collect_num":"1335","food_str":"瘦猪肉 生菜 豆瓣酱 干辣椒 花椒","num":1335},{"id":"46968","title":"红糖苹果银耳汤","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/47/46968.jpg","collect_num":"1244","food_str":"银耳 苹果 红糖","num":1244},{"id":"10191","title":"麻婆豆腐","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/11/10191.jpg","collect_num":"1212","food_str":"豆腐 肉末 生抽 白糖 芝麻油","num":1212},{"id":"2372","title":"皮蛋瘦肉粥","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/3/2372.jpg","collect_num":"1143","food_str":"大米 皮蛋 猪肉 油条 香葱","num":1143},{"id":"2166","title":"蚂蚁上树","pic":"http://www.qubaobei.com/ios/cf/uploadfile/132/3/2166.jpg","collect_num":"1138","food_str":"红薯粉 肉 姜 蒜 花椒","num":1138}] */ private int ret; private List<DataBean> data; public int getRet() { return ret; } public void setRet(int ret) { this.ret = ret; } public List<DataBean> getData() { return data; } public void setData(List<DataBean> data) { this.data = data; } }
全局代码文件httpservice文件夹下FoodHttpService.java
package com.estyle.day0127.httpservice; import com.estyle.day0127.bean.FoodBean; import io.reactivex.Observable; import retrofit2.http.GET; import retrofit2.http.Query; public interface FoodHttpService { @GET("ios/cf/dish_list.php?stage_id=1&limit=10") Observable<FoodBean> getObservable(@Query("page") int page); }