android开发-城市选择页面

本文介绍了一个Android城市选择页面的实现,采用ViewModel+LiveData+Room架构,结合retrofit+rxjava+okhttp3进行网络请求,并利用数据库存储和更新数据。详细讲解了网络接口、数据库操作、数据展示及UI组件的实现,包括RecycleView适配器、标题悬浮栏和右侧滑动栏的控制。
摘要由CSDN通过智能技术生成

  首先看一下效果动图:         



数据来源是公司的一个api,网址就不贴了,数据格式大概是这样:

数据Bean:

  • public class BaseBean implements Serializable {
        private String Code;
        private String Message;
        public String getCode() {
            return Code;
        }
        public void setCode(String code) {
            Code = code;
        }
        public String getMessage() {
            return Message;
        }
        public void setMessage(String message) {
            Message = message;
        }
        public boolean isSuccessful() {
            return TextUtils.equals("1", getCode());
        }
    }
  • public class Areas extends BaseBean {
        private Map<String, List<Cities>> Area;
        private List<Cities> HotCities;
        private String Version;
        public Map<String, List<Cities>> getArea() {
            return Area;
        }
        public void setArea(Map<String, List<Cities>> area) {
            Area = area;
        }
        public List<Cities> getHotCities() {
            return HotCities;
        }
        public void setHotCities(List<Cities> hotCities) {
            HotCities = hotCities;
        }
        public String getVersion() {
            return Version;
        }
        public boolean isSucceed() {
            return "1".equals(Version);
        }
        public void setVersion(String version) {
            Version = version;
        }
    }
    
  • @Entity(tableName = "city_table")
    public class Cities {
    
        /**
         * Province : 四川省
         * ProvinceId : 23
         * City : 阿坝藏族羌族自治州
         * CityId : 2362
         * District : 阿坝藏族羌族自治州
         * DistrictId : 2362
         * PinYin : aba
         */
    
        @PrimaryKey(autoGenerate = true)
        private int Id;
    
        private int CityId;
    
        private String Province;
    
        private int ProvinceId;
    
        private String City;
    
        private String District;
    
        private int DistrictId;
    
        private String PinYin;
        /**
         * 忽略该属性
         */
        @Ignore
        private List<Cities> mtags;
        /**
         * 忽略该属性
         */
        @Ignore
        public int position;
    
        /**
         * @param tag   属于哪个字母
         * @param tagid -9 代表当前定位城市标题、热门城市标题、 字母组标题
         *              -8 代表当前定位城市
         *              -7 热门城市
         */
        public static Cities newCities(String tag, int tagid) {
            Cities cit = new Cities();
            cit.setDistrict(tag);
            cit.setId(tagid);
            return cit;
        }
    
        public static Cities newCities(String tag, int tagid,int position) {
            Cities cit = new Cities();
            cit.setDistrict(tag);
            cit.setId(tagid);
            cit.position = position;
            return cit;
        }
    
    
        public int getId() {
            return Id;
        }
    
        public int getViewType() {
            int cityid;
            switch (Id) {
                case -9:
                    cityid = 0;
                    break;
                case -8:
                    cityid = 1;
                    break;
                case -7:
                    cityid = 2;
                    break;
                case -10:
                    cityid = 4;
                    break;
                default:
                    cityid = 3;
                    break;
            }
            return cityid;
        }
    
        public void setId(int id) {
            Id = id;
        }
    
        public List<Cities> getMtags() {
            return mtags;
        }
    
        public void setMtags(List<Cities> mtags) {
            this.mtags = mtags;
        }
    
        public String getProvince() {
            return Province;
        }
    
        public void setProvince(String Province) {
            this.Province = Province;
        }
    
        public int getProvinceId() {
            return ProvinceId;
        }
    
        public void setProvinceId(int ProvinceId) {
            this.ProvinceId = ProvinceId;
        }
    
        public String getCity() {
            return City;
        }
    
        public void setCity(String City) {
            this.City = City;
        }
    
        public int getCityId() {
            return CityId;
        }
    
        public void setCityId(int CityId) {
            this.CityId = CityId;
        }
    
        public String getDistrict() {
            return District;
        }
    
        public void setDistrict(String District) {
            this.District = District;
        }
    
        public int getDistrictId() {
            return DistrictId;
        }
    
        public void setDistrictId(int DistrictId) {
            this.DistrictId = DistrictId;
        }
    
        public String getPinYin() {
            return PinYin;
        }
    
        public void setPinYin(String PinYin) {
            this.PinYin = PinYin;
        }
    }

可以看出在city类中配置了一些属性,主要是为了缓存它,整个的设计框架采用的是ViewModel+LiveData+Room,关于这个框架之前我已经详细写过一篇了,所以,这里不做详述;

实现的主要思路是:

1.使用retrofit+rxjava+okhttp3进行网络请求,

api接口:

public interface CitiesService {
    /**
     * 选择城市相关的网络请求
     */
    @FormUrlEncoded
    @POST("api地址")
    Observable<Areas> getCities(@Field("version") String version);
}

网络获取工具

public class NetWork {
    private static SparseArray<NetWork> retrofitManagers = new SparseArray<>();
    private Retrofit mRetrofit;
    private NetWork(int hostType) {
        Gson gson = new GsonBuilder()
                //配置你的Gson
                .setDateFormat("yyyy-MM-dd hh:mm:ss")
                .create();
        mRetrofit = new Retrofit.Builder()
                .client(getFreeClient())
                .baseUrl(Constant.getHost(hostType))
                .addConverterFactory(ScalarsConverterFactory.create())//直接将数据转换为String
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
    }
    private  OkHttpClient getFreeClient() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        X509TrustManager[] trustManager = new X509TrustManager[]{
                new X509TrustManager() {
                    @Override
                    public void checkClientTrusted(X509Certificate[] chain, String authType) throws
                            CertificateException {
                    }

                    @Override
                    public void checkServerTrusted(X509Certificate[] chain, String authType) throws
                            CertificateException {
                    }

                    @Override
                    public X509Certificate[] getAcceptedIssuers() {
                        return new X509Certificate[]{};
                    }
                }
        };
        try {
            SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustManager, new SecureRandom());
            SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
            if (sslSocketFactory != null)
                builder.sslSocketFactory(sslSocketFactory);
            builder.hostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
        logging.setLevel(HttpLoggingInterceptor.Level.BODY);
        builder.addInterceptor(logging);
        builder.connectTimeout(20, TimeUnit.SECONDS);
        builder.writeTimeout(20, TimeUnit.SECONDS).readTimeout(20, TimeUnit.SECONDS);
        builder.retryOnConnectionFailure(true);
        return builder.build();
    }
    public static NetWork getInstance(int hostType) {
        NetWork retrofitManager = retrofitManagers.get(hostType);
        if (retrofitManager == null) {
            retrofitManager = new NetWork(hostType);
            retrofitManagers.put(hostType, retrofitManager);
            return retrofitManager;
        }
        return retrofitManager;
    }
    /**
     * @param service 服务接口
     * @return T
     */
    public <T> T createService(final Class<T> service) {
        return mRetrofit.create(service);
    }
}

这里为了避免有多个retrofit生成,造成内存不足,使用了SparyArray去将每一个网络工具实例类存储 ,可以达到复用的效果;

2.数据库存储

BaseDb:数据库配置:

@Database(entities = {Cities.class}, version = 1)
public abstract class BaseDB extends RoomDatabase {
    public abstract CityDao cityDao();
    private static BaseDB INSTANCE;
    private static final Object sLock = new Object();
    public static BaseDB getInstance(Context context) {
        synchronized (sLock) {
            if (INSTANCE == null) {
                INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
                        BaseDB.class, "city").allowMainThreadQueries().build();
            }
            return INSTANCE;
        }
    }
}

数据库操作类:CityDao

@Dao
public interface CityDao {
    @Query("SELECT COUNT(1) from city_table")
    int getDBDataCount();
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void insertCitys(List<Cities> cities);
    @Query("SELECT * from city_table where PinYin like '%' + :searStr +'%' or District like '%'+:searStr+ '%'" )
    List<Cities> getAllCitiesData(String searStr);
}

viewModel类:数据的容器

public class BaseViewModel<T> extends ViewModel {
    //Disposable 容器,拿到一个Disposable就执行clear,解除订阅事件
    private final CompositeDisposable mDisposable = new CompositeDisposable();
    //LiveData封装类,添加/消除数据源
    private MutableLiveData<T> mTMutableLiveData = new MutableLiveData<>();
    //LiveData的set,post方法,同步,异步设置数据
    protected void setValue(T value) {
        mTMutableLiveData.setValue(value);
    }
    protected void postValue(T value) {
        mTMutableLiveData.postValue(value);
    }
    //添加一个Disposable到集合中
    protected void add(Di
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值