第一个安卓应用开发记录

一、项目框架的搭建

1、在git上新建一个coolweather的仓库
2、新建一个Coolweather项目,添加到git版本管理
3、在java中新建几个包,db:用于存放数据库模型相关的代码,gson:用于存放GSon相关的代码,service:用于存放服务相关的代码,util包用于存放工具相关代码
4、添加项目依赖的第三方,在app/build.gradle
依赖:

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0-alpha3'
    implementation 'com.android.support.constraint:constraint-layout:1.1.2'
    implementation 'org.litepal.android:core:2.0.0'
    implementation 'com.squareup.okhttp3:okhttp:3.10.0'
    implementation 'com.google.code.gson:gson:2.8.5'
    implementation 'com.github.bumptech.glide:glide:4.7.1'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.7.1'

    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}

仓库添加

allprojects {
    repositories {
        mavenCentral()
        google()
        jcenter()
    }
}

说明:
implementation 'org.litepal.android:core:2.0.0'是数据库操作的框架
implementation 'com.squareup.okhttp3:okhttp:3.10.0'网络请求框架
implementation 'com.google.code.gson:gson:2.8.5' JSON解析框架
implementation 'com.github.bumptech.glide:glide:4.7.1' annotationProcessor 'com.github.bumptech.glide:compiler:4.7.1'为加载图片的框架

二、数据库表的设计

1、数据获取
省份获取接口:
http://guolin.tech/api/china
获取的数据如下:
[{"id":1,"name":"北京"},{"id":2,"name":"上海"}]
省下面对应的市获取接口
http://guolin.tech/api/china/22,其中22为省份的id,数据结构如下:
[{"id":191,"name":"长沙"},{"id":192,"name":"湘潭"},{"id":193,"name":"株洲"},{"id":194,"name":"衡阳"},{"id":195,"name":"郴州"},{"id":196,"name":"常德"},{"id":197,"name":"益阳"},{"id":198,"name":"娄底"},{"id":199,"name":"邵阳"},{"id":200,"name":"岳阳"},{"id":201,"name":"张家界"},{"id":202,"name":"怀化"},{"id":203,"name":"永州"},{"id":204,"name":"吉首"}]
获取区对应的信息
http://guolin.tech/api/china/22/191,其中191为市的id
[{"id":1422,"name":"长沙","weather_id":"CN101250101"},{"id":1423,"name":"宁乡","weather_id":"CN101250102"},{"id":1424,"name":"浏阳","weather_id":"CN101250103"},{"id":1425,"name":"马坡岭","weather_id":"CN101250104"},{"id":1426,"name":"望城","weather_id":"CN101250105"}]
最后通过weather_id 获取天气信息,使用和风天气的api
https://console.heweather.com/register?role=personal,注册免费

天气信息的获取
https://free-api.heweather.com/s6/weather/now?location=CN101250101&key=22c4dc1c0a3245c7a97e7c2543b9781a
数据如下:
{"HeWeather6":[{"basic":{"cid":"CN101250101","location":"长沙","parent_city":"长沙","admin_area":"湖南","cnty":"中国","lat":"28.19408989","lon":"112.98227692","tz":"+8.00"},"update":{"loc":"2018-07-06 16:49","utc":"2018-07-06 08:49"},"status":"ok","now":{"cloud":"75","cond_code":"104","cond_txt":"阴","fl":"31","hum":"85","pcpn":"0.0","pres":"1000","tmp":"29","vis":"13","wind_deg":"293","wind_dir":"西北风","wind_sc":"3","wind_spd":"19"}}]}

2、数据库表实现
新建Province类 继承LitePalSupport

public class Province extends LitePalSupport {
    private int id;
    private String provinceName;
    private int provinceCode;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getProvinceName() {
        return provinceName;
    }

    public void setProvinceName(String provinceName) {
        this.provinceName = provinceName;
    }

    public int getProvinceCode() {
        return provinceCode;
    }

    public void setProvinceCode(int provinceCode) {
        this.provinceCode = provinceCode;
    }
}

City类

public class City extends LitePalSupport {
    private  int id;
    private String cityName;
    private int cityCode;
    private  int provinceId;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getCityName() {
        return cityName;
    }

    public void setCityName(String cityName) {
        this.cityName = cityName;
    }

    public int getCityCode() {
        return cityCode;
    }

    public void setCityCode(int cityCode) {
        this.cityCode = cityCode;
    }

    public int getProvinceId() {
        return provinceId;
    }

    public void setProvinceId(int provinceId) {
        this.provinceId = provinceId;
    }
}

Country类

public class Country extends LitePalSupport {
    private int id;
    private String countryName;
    private String weatherId;
    private int cityId;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getCountryName() {
        return countryName;
    }

    public void setCountryName(String countryName) {
        this.countryName = countryName;
    }

    public String getWeatherId() {
        return weatherId;
    }

    public void setWeatherId(String weatherId) {
        this.weatherId = weatherId;
    }

    public int getCityId() {
        return cityId;
    }

    public void setCityId(int cityId) {
        this.cityId = cityId;
    }
}

在app/src/main 目录在新建assets 文件,在改目录下新建一个litepal.xml文件,编辑内容如下:




    
    

    
    


    
        
        
        
    

    


最后需要在配置一下LitePalApplication,修改如下:




    
        
            
                

                
            
        
    


3、自定义Fragment

首先定义一个线性布局如下



    

        

        

这里自定义了导航条,所以需要修改style.xml文件,修改如下:



    
    


新建一个ChooseAreaFragment继承Fragment,代码如下:

public class ChooseAreaFragment extends Fragment {
    public static final  int LEVEL_PROVINCE = 0;
    public static final  int LEVEL_CITY = 1;
    public static final  int LEVEL_COUNTRY = 2;
    private static final  String TYPE_PROVINCE = "province";
    private static final  String TYPE_City = "city";
    private static final  String TYPE_Country = "country";


    private ProgressDialog progressDialog;
    private TextView titleText;
    private Button backButton;
    private ListView listView;
    private ArrayAdapter adapter;
    private List dataList = new ArrayList<>();

    private List provinceList;
    private List cityList;
    private List countryList;

    private Province selectedProvince;
    private City selectedCity;
    private int currentLevel;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.choose_area,container,false);
        titleText = (TextView)view.findViewById(R.id.title_text);
        backButton = (Button)view.findViewById(R.id.btn_back);
        listView = (ListView)view.findViewById(R.id.listView);

        adapter = new ArrayAdapter<>(getContext(),android.R.layout.simple_list_item_1,dataList);
        listView.setAdapter(adapter);
        return view;

    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView adapterView, View view, int i, long l) {
                if (currentLevel == LEVEL_PROVINCE){
                    selectedProvince = provinceList.get(i);
                    queryCities();
                }else if (currentLevel == LEVEL_CITY){
                    selectedCity = cityList.get(i);
                    queryCounties();
                }
            }
        });

        backButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (currentLevel == LEVEL_COUNTRY){
                    queryCities();
                }else if (currentLevel == LEVEL_CITY){
                    queryProinces();
                }
            }


        });

        queryProinces();
    }

    private void queryCounties() {

        titleText.setText(selectedCity.getCityName());
        backButton.setVisibility(View.VISIBLE);
        countryList = LitePal.where("cityid = ?",String.valueOf(selectedCity.getId())).find(Country.class);
        if (countryList.size()>0){
            dataList.clear();
            for (Country country:countryList){
                dataList.add(country.getCountryName());
            }
            adapter.notifyDataSetChanged();;
            listView.setSelection(0);
            currentLevel = LEVEL_COUNTRY;
        }else {

            int provinceCode = selectedProvince.getProvinceCode();
            int cityCode = selectedCity.getCityCode();
            String address = "http://guolin.tech/api/china/" + provinceCode + "/" + cityCode;
            queryFromServer(address,TYPE_Country);
        }
    }

    private void queryCities() {
        titleText.setText(selectedProvince.getProvinceName());
        backButton.setVisibility(View.VISIBLE);
        cityList = LitePal.where("provinceid = ?",String.valueOf(selectedProvince.getId())).find(City.class);
        if (cityList.size()>0){
            dataList.clear();
            for (City city:cityList){
                dataList.add(city.getCityName());
            }
            adapter.notifyDataSetChanged();;
            listView.setSelection(0);
            currentLevel = LEVEL_CITY;
        }else {

            int provinceCode = selectedProvince.getProvinceCode();
            String address = "http://guolin.tech/api/china/" + provinceCode;
            queryFromServer(address,TYPE_City);
        }
    }
    private void queryProinces() {
        titleText.setText("中国");
        backButton.setVisibility(View.GONE);
        provinceList = LitePal.findAll(Province.class);
        if (provinceList.size()>0){
            dataList.clear();
            for (Province province:provinceList){
                dataList.add(province.getProvinceName());
            }
            adapter.notifyDataSetChanged();
            listView.setSelection(0);
            currentLevel = LEVEL_PROVINCE;
        }else {
            String address = "http://guolin.tech/api/china";
            queryFromServer(address,TYPE_PROVINCE);
        }
    }

    private void queryFromServer(String address,final String type){
        showProgressDialog();

        HttpUtil.sendHttpRequest(address, new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
               getActivity().runOnUiThread(new Runnable() {
                   @Override
                   public void run() {
                       closeProgressDialog();
                       Toast.makeText(getContext(),"加载失败",Toast.LENGTH_SHORT).show();;
                   }
               });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                //在这里解析数据
                String responseText = response.body().string();

                Log.d(TAG, "onResponse: " + responseText);
                boolean result = false;
                if (type.equals(TYPE_PROVINCE)){
                    result = Utility.handleProvinceResponse(responseText);
                }else if(type.equals(TYPE_City)){
                    result = Utility.handleCityResponse(responseText,selectedProvince.getId());
                }else if(type.equals(TYPE_Country)){
                    result = Utility.handleCountryResponse(responseText,selectedCity.getId());
                }

                if (result){
                    getActivity().runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            closeProgressDialog();
                            if (type.equals(TYPE_PROVINCE)){
                                queryProinces();
                            }else if(type.equals(TYPE_City)){
                                queryCities();
                            }else if(type.equals(TYPE_Country)){
                                queryCounties();
                            }
                        }
                    });
                }
            }
        });
    }


    private void showProgressDialog(){
        if (progressDialog == null){
            progressDialog = new ProgressDialog(getActivity());
            progressDialog.setMessage("正在加载");
            progressDialog.setCanceledOnTouchOutside(false);
        }
        progressDialog.show();
    }

    private void closeProgressDialog(){
        if (progressDialog!=null){
            progressDialog.dismiss();
        }
    }
}

在activity_main.xml文件中添加Fragment布局如下:




    


三、展示天气数据

效果如下:


第一个安卓应用开发记录_第1张图片
780FA754-69A3-440F-AFC3-297954E7F328.png

将上图的界面拆分成三个布局:1、导航部分(展示城市和更新时间)
2、现在天气信息 3、未来三天信息展示
1、导航部分,新建一个title.xml,代码如下:





    

2、天气信息部分




    

    


3、未来天气布局forcast.xml代码如下:




    

    
    



forecast_item.xml文件




    

    


    

    


四、生成APK文件

https://blog.csdn.net/wyg1230/article/details/77529465/

你可能感兴趣的:(第一个安卓应用开发记录)