实现效果
MVC设计模式
Utils工具类
public class OkhttpUtils {
private static final int time = 60*1000;
private static OkhttpUtils okhttpUtils = null;
private OkHttpClient client;//client
private Handler handler = new Handler();//主线程回调
private OkhttpUtils(){
//设置拦截器
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
//单例创建client
client = new OkHttpClient.Builder()
.connectTimeout(time, TimeUnit.MILLISECONDS)
.writeTimeout(time, TimeUnit.MILLISECONDS)
.readTimeout(time, TimeUnit.MILLISECONDS)
.build();
}
//双重校验锁
public static OkhttpUtils getInstance(){
if (okhttpUtils == null){
synchronized (String.class){
if (okhttpUtils == null){
okhttpUtils = new OkhttpUtils();
}
}
}
return okhttpUtils;
}
/**
* get请求json数据
*
* @param url 网络接口
* @param myOkhttpCallBack 接口返回数据
*/
public void doGet(String url, final MyOkhttpCallBack myOkhttpCallBack, final int code) {
Request request = new Request.Builder()
.url(url)
.get()
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
final String message = e.getMessage();
//子线程
handler.post(new Runnable() {
@Override
public void run() {
//主线程
if (myOkhttpCallBack != null) {
myOkhttpCallBack.onError(message);
}
}
});
}
@Override
public void onResponse(Call call, Response response) throws IOException {
final String json = response.body().string();
//子线程
handler.post(new Runnable() {
@Override
public void run() {
//主线程
if (myOkhttpCallBack != null) {
myOkhttpCallBack.onOk(json,code);
}
}
});
}
});
}
}
callback回调
public interface MyOkhttpCallBack {
void onOk(String json,int code);
void onError(String message);
}
Model层
model接口
public interface HomeModel {
void getBannerData(MyOkhttpCallBack myOkhttpCallBack);//轮播图数据
void getMenuData(MyOkhttpCallBack myOkhttpCallBack);//中间菜单数据
void getTypeData(MyOkhttpCallBack myOkhttpCallBack);//产品分类
}
modelImpl
public class HomeModelImpl implements HomeModel {
@Override
public void getBannerData(MyOkhttpCallBack myOkhttpCallBack) {
OkhttpUtils.getInstance().doGet(NetConfig.BANNER_URL,myOkhttpCallBack,NetConfig.CODE_BANNER);
}
@Override
public void getMenuData(MyOkhttpCallBack myOkhttpCallBack) {
OkhttpUtils.getInstance().doGet(NetConfig.MENU_RUL,myOkhttpCallBack,NetConfig.CODE_MENU);
}
@Override
public void getTypeData(MyOkhttpCallBack myOkhttpCallBack) {
OkhttpUtils.getInstance().doGet(NetConfig.TYPE_URL,myOkhttpCallBack,NetConfig.CODE_TYPE);
}
}
创建Base包
base包可以使代码变得简洁,主要是Activity和Fragment
Activity——Base包
public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(layoutId());//不写具体布局
initView();
initData();
}
protected abstract void initData();//初始化数据
protected abstract void initView();//初始化控件
protected abstract int layoutId();//加载布局
//页面跳转
public void startActivity(Class class_){
Intent intent = new Intent(this,class_);
startActivity(intent);
}
}
Fragment——Base包
public abstract class BaseFragment extends Fragment {
private View view;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(layoutId(), container, false);
initView(view);//传入view
initData();
return view;
}
protected abstract void initData();
protected abstract void initView(View view);
public abstract int layoutId();
}
主页面样式
布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="15"></androidx.viewpager.widget.ViewPager>
<com.flyco.tablayout.CommonTabLayout
android:id="@+id/common"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
app:tl_iconHeight="20dp"
app:tl_iconWidth="20dp"
app:tl_textSelectColor="#2196F3"
app:tl_textUnselectColor="#000"
app:tl_textsize="10sp"></com.flyco.tablayout.CommonTabLayout>
</LinearLayout>
主页面的代码
public class MainActivity extends BaseActivity {
private ViewPager viewpager;
private CommonTabLayout common;
private ArrayList<CustomTabEntity> list = new ArrayList<>();
private List<Fragment> fragmentList = new ArrayList<>();
private FragmentAdapter fragmentAdapter;
@Override
protected void initData() {
}
@Override
protected void initView() {
initRegister();
common = (CommonTabLayout) findViewById(R.id.common);
list.add(new MyTabEntity("首页", R.drawable.select_1, R.drawable.default_1));
list.add(new MyTabEntity("供应", R.drawable.select_2, R.drawable.default_2));
list.add(new MyTabEntity("品牌", R.drawable.select_3, R.drawable.default_3));
list.add(new MyTabEntity("个人中心", R.drawable.select_4, R.drawable.default_4));
common.setTabData(list);
viewpager = (ViewPager) findViewById(R.id.viewpager);
fragmentList.add(new HomeFragment());
fragmentList.add(new GongyingFragment());
fragmentList.add(new PinpaiFragment());
fragmentList.add(new MyFragment());
fragmentAdapter = new FragmentAdapter(getSupportFragmentManager(), fragmentList);
viewpager.setAdapter(fragmentAdapter);
//TODO:点击底部切换
common.setOnTabSelectListener(new OnTabSelectListener() {
@Override
public void onTabSelect(int position) {
viewpager.setCurrentItem(position);
}
@Override
public void onTabReselect(int position) {
}
});
//TODO:滑动切换
viewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
common.setCurrentTab(position);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
private void initRegister() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.ACCESS_NETWORK_STATE,
Manifest.permission.ACCESS_WIFI_STATE,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.ACCESS_COARSE_LOCATION
}, 100);
}
}
@Override
protected int layoutId() {
return R.layout.activity_main;
}
}
Fragment
布局样式
<?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"
tools:context=".fragment.HomeFragment">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#2196F3">
<LinearLayout
android:gravity="center_vertical"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:src="@drawable/sao"
android:layout_width="25dp"
android:layout_height="25dp">
</ImageView>
<TextView
android:drawablePadding="5dp"
android:padding="5dp"
android:drawableLeft="@drawable/icon_seacher"
android:gravity="center_vertical"
android:textColor="@color/colorWhite"
android:text="请输入要搜索的信息"
android:background="@drawable/shape_search_bg"
android:layout_marginRight="10dp"
android:layout_marginLeft="10dp"
android:id="@+id/tv_search"
android:layout_width="270dp"
android:layout_height="30dp">
</TextView>
<ImageView
android:src="@drawable/man"
android:layout_width="25dp"
android:layout_height="25dp">
</ImageView>
</LinearLayout>
</androidx.appcompat.widget.Toolbar>
<com.youth.banner.Banner
android:id="@+id/banner"
android:layout_width="match_parent"
android:layout_height="160dp"></com.youth.banner.Banner>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_menu"
android:layout_width="match_parent"
android:layout_height="190dp"></androidx.recyclerview.widget.RecyclerView>
<View
android:layout_width="match_parent"
android:layout_height="8dp"
android:background="#eee"></View>
<TextView
android:textColor="#52B2F4"
android:padding="3dp"
android:text="产品分类"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_type"
android:layout_width="match_parent"
android:layout_height="190dp"></androidx.recyclerview.widget.RecyclerView>
</LinearLayout>
定义一个Net文件存储需要用到接口及常量
public class NetConfig {
//接口前段地址
public static final String BASE_URL = "http://api.yunzhancn.cn/api/app.interface.php?siteid=78703&";
//首页头部banner轮播接口 itemid=2&act=ad_app
public static final String BANNER_URL = BASE_URL + "itemid=2&act=ad_app";
//首页中间菜单接口 act=column&ctype=4
public static final String MENU_RUL = BASE_URL + "act=column&ctype=4";
//首页产品分类接口 act=column&ctype=2&mid=16
public static final String TYPE_URL = BASE_URL + "act=column&ctype=2&mid=16";
//区分同一个页面,不同请求的数据
public static final int CODE_BANNER = 101;
public static final int CODE_MENU = 102;
public static final int CODE_TYPE = 103;
}
Home页面核心代码
public class HomeFragment extends BaseFragment implements MyOkhttpCallBack {
private HomeModel homeModel;
private TextView tv_search;
private Banner banner;
private RecyclerView rvMenu;
private RecyclerView rvType;
private ArrayList<String> list_image = new ArrayList<>();
private ArrayList<MenuEntity> list_menu = new ArrayList<>();
private ArrayList<TypeEntity> list_type = new ArrayList<>();
private MyMenuAdapter menuAdapter;
private MyFenAdapter fenAdapter;
@Override
protected void initData() {
homeModel = new HomeModelImpl();
//TODO:banner数据
homeModel.getBannerData(this);
//TODO:menu数据
homeModel.getMenuData(this);
//TODO:type数据
homeModel.getTypeData(this);
}
@Override
protected void initView(View view) {
tv_search = (TextView) view.findViewById(R.id.tv_search);
banner = (Banner) view.findViewById(R.id.banner);
rvMenu = (RecyclerView) view.findViewById(R.id.rv_menu);
menuAdapter = new MyMenuAdapter(R.layout.item_menu, list_menu);
rvMenu.setAdapter(menuAdapter);
rvMenu.setLayoutManager(new GridLayoutManager(getContext(), 4));
rvType = (RecyclerView) view.findViewById(R.id.rv_type);
fenAdapter = new MyFenAdapter(R.layout.item_fenlei,list_type);
rvType.setAdapter(fenAdapter);
rvType.setLayoutManager(new GridLayoutManager(getContext(), 4));
//搜索
Drawable drawable=getResources().getDrawable(R.drawable.icon_seacher);//放大镜
drawable.setBounds(0,0,50,50);//第一0是距左边距离,第二0是距上边距离 30 30 宽度和高度
tv_search.setCompoundDrawables(drawable,null,null,null);//textView设置左边图片
}
@Override
public int layoutId() {
return R.layout.fragment_home;
}
@Override
public void onOk(String json, int code) {
//TODO 1:必须是网络请求成功之后
if (code == NetConfig.CODE_BANNER) {
//原生解析数组
try {
JSONArray jsonArray = new JSONArray(json);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
String image_src = jsonObject.getString("image_src");
list_image.add(image_src);
}
} catch (JSONException e) {
e.printStackTrace();
}
banner.setImages(list_image);//设置图片集合
banner.setImageLoader(new ImageLoader() {//设置图屁啊家加载起
@Override
public void displayImage(Context context, Object path, ImageView imageView) {
Glide.with(context).load(path).into(imageView);
}
});
banner.start();//启动
} else if (code == NetConfig.CODE_MENU) {
list_menu.clear();
Gson gson = new Gson();
ArrayList<MenuEntity> menuEntities = gson.fromJson(json, new TypeToken<ArrayList<MenuEntity>>() {
}.getType());
list_menu.addAll(menuEntities);
menuAdapter.notifyDataSetChanged();
}else if (code == NetConfig.CODE_TYPE){
list_type.clear();
Gson gson = new Gson();
ArrayList<TypeEntity> typeEntities = gson.fromJson(json, new TypeToken<ArrayList<TypeEntity>>() {
}.getType());
list_type.addAll(typeEntities);
fenAdapter.notifyDataSetChanged();
}
}
@Override
public void onError(String message) {
Toast.makeText(getActivity(), "" + message, Toast.LENGTH_SHORT).show();
}
}