zoukankan      html  css  js  c++  java
  • android开发练习:天气应用

    来源:网易云课堂GeekBand第七次作业

    作业要求:
    做一个天气应用

    1. 接口参考: http://apistore.baidu.com/apiworks/servicedetail/880.html,只是参考API,可自行查找使用其他API接口
    2. 考察内容:获取数据,解析JSON
    3. 数据缓存在数据库中,使用ContentProvider来处理
    4. 如果不强制刷新,则使用缓存数据每隔一定时间再刷新一次

    前期准备

    1.选择合适的API!选择合适的API!选择合适的API!(重要的话说三遍,中途变更API严重影响效率和心情).
    2.gson.如何添加依赖库 http://www.cnblogs.com/happyhacking/p/5257002.html

    目录结构

    UI

    注意:在布局的过程中weightSum和layout_weight要慎用,尤其是在内容长度可变的情况下,使用结果往往不符合预期.

    主要逻辑

    主要逻辑集中在查询按钮的点击事件上

    (注意:cursor.moveToFirst(),Long.valueOf()和Long.getLong()的用法.)

     mQueryButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //判断用户是否输入了城市名称
                    if (!TextUtils.isEmpty(mCityName.getText())) {
                        //首先查询本地数据库
                        Uri uri = Uri.parse("content://com.example.janiszhang.weatherdemo.provider/weatherdata");
                        Cursor cursor = getContentResolver().query(uri, null, "cityname = ?", new String[]{mCityName.getText() + ""}, null);
                        if (cursor.moveToFirst()) {// 查询成功    //这里不可以使用cursor!= null来判断!!!!
                            Log.i("zhangbz", cursor.getString(cursor.getColumnIndex("savetime")));
    
                           if ((System.currentTimeMillis() - Long.valueOf(cursor.getString(cursor.getColumnIndex("savetime")))) < (1000*60)) {//这里不可以使用Long.getLong(),因为它返回的是系统属性的值,其参数是被请求的系统属性的名称
                               //如果数据库中的数据没有过期,就从数据库中查询
                               updateUIfromDatabase(cursor);
                           } else {
                               //如果数据库中的数据过期了,则通过网络查询并update到数据库
                               shouldUpdate = true;
                               try {
                                   httpArg = "city=" + URLEncoder.encode(mCityName.getText().toString(), "UTF-8");//中文需要编码
                               } catch (UnsupportedEncodingException e) {
                                   e.printStackTrace();
                               }
                               new MyAsyncTask().execute(httpArg);//使用asynctask
    
                           }
                        } else {
                            //网络查询并insert到数据库
                            shouldUpdate = false;//需要insert
                            try {
                                httpArg = "city=" + URLEncoder.encode(mCityName.getText().toString(), "UTF-8");//中文需要编码
                            } catch (UnsupportedEncodingException e) {
                                e.printStackTrace();
                            }
                            new MyAsyncTask().execute(httpArg);
                        }
    
                        
                        SharedPreferences sp = getSharedPreferences("last", Context.MODE_PRIVATE);
                        SharedPreferences.Editor editor = sp.edit();
                        editor.putString("cityname", mCityName.getText().toString());
                        editor.apply();
                        
                        //开启自动更新
                        Intent intent = new Intent(MainActivity.this, AutoUpdateService.class);
                        startService(intent);
                    }
                }
            });
    

    重点记录

    使用Gson解析数据

                Gson gson = new Gson();
                WeatherDataStatus weatherDataStatus = gson.fromJson(s, WeatherDataStatus.class);
    

    这里注意两个问题:
    1.使用gson解析json数据时,不需要为整个json数据创建实体类,只需要为需要解析的数据定义变量和提供getter/setter方法.
    2.注意区分什么是json数组:

            //json数组:中括号
            [{
    		"这是json数组": "这是json数组"
    	}, {
    		"这是json数组": "这是json数组"
    	}, {
    		"这是json数组": "这是json数组"
    	}]
    
            
           //注意和这种情况区分开
           {
    	    "这不是json数组": [{
    		"这才是json数组": "这才是json数组"
    	    }, {
    		"这才是json数组": "这才是json数组"
    	    }, {
    		"这才是json数组": "这才是json数组"
    	    }]
           }
    

    自动更新的实现

    service需要由Activity启动,之后由service和receiver配合相互唤醒.

    AutoUpdateService.class

    public class AutoUpdateService extends Service{
    
        private String mCityname;
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            //在子线程中发起网络请求,将请求结果保存到数据库中
            new Thread(new Runnable() {
                @Override
                public void run() {
                    updateWeather();
                }
            }).start();
    
            //使用AlarmManager实现定时任务
            AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
            int anHour = 8 * 60 *60 * 1000;//8小时
            long triggerAtTime = SystemClock.elapsedRealtime() + anHour;
            //service -> receiver
            Intent i = new Intent(this, AutoUpdateReceiver.class);
            PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, 0);
            manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi);
            
            return super.onStartCommand(intent, flags, startId);
        }
        //...
    
    }
    

    AutoUpdateReceiver.class

    public class AutoUpdateReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {
            //receiver->service
            Intent i = new Intent(context, AutoUpdateService.class);
            context.startService(i);
        }
    }
    

    contentprovider的练习

    虽然用在这里很牵强,但是目的是练习嘛.
    很久没有使用contentprovider,以下为基本使用方法.

    public class MyProvider extends ContentProvider{
    
        public static final int WEATHERDATA_DIR = 0;
        public static final String AUTHORITY = "com.example.janiszhang.weatherdemo.provider";
        private static UriMatcher sUriMatcher;
        private MyDBHelper mMyDBHelper;
    
        static {
            sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
            sUriMatcher.addURI(AUTHORITY, "weatherdata", WEATHERDATA_DIR);
        }
        @Override
        public boolean onCreate() {
            mMyDBHelper = new MyDBHelper(getContext(),  "weatherDataDB.db", null, 1);
            return true;
        }
    
        @Nullable
        @Override
        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
            SQLiteDatabase db = mMyDBHelper.getReadableDatabase();
            Cursor cursor = null;
            switch (sUriMatcher.match(uri)) {
                case WEATHERDATA_DIR:
                    cursor = db.query("weatherdata", projection, selection, selectionArgs, null, null, sortOrder);
                    break;
            }
            return cursor;
        }
    
        @Nullable
        @Override
        public String getType(Uri uri) {
            switch (sUriMatcher.match(uri)) {
                case WEATHERDATA_DIR:
                    return "vnd.android.cursor.dir/vnd.com.example.janiszhang.weatherdemo.provider.weatherdata";
            }
            return null;
        }
    
        @Nullable
        @Override
        public Uri insert(Uri uri, ContentValues values) {
    
            SQLiteDatabase db = mMyDBHelper.getReadableDatabase();
            Uri uriReturn = null;
            switch (sUriMatcher.match(uri)) {
                case WEATHERDATA_DIR:
                    long newId = db.insert("weatherdata", null, values);
                    uriReturn = Uri.parse("content://" + AUTHORITY + "/weatherdata/" + newId);
                    break;
            }
            return uriReturn;
        }
    
        @Override
        public int delete(Uri uri, String selection, String[] selectionArgs) {
            return 0;
        }
    
        @Override
        public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
            SQLiteDatabase db = mMyDBHelper.getWritableDatabase();
            int updateRows = 0;
            switch (sUriMatcher.match(uri)) {
                case WEATHERDATA_DIR:
                    updateRows = db.update("weatherdata", values, selection, selectionArgs);
                    break;
            }
            return updateRows;
        }
    }
    

    github地址:https://github.com/zhangbz/WeatherDemo

    总结:写这个demo,把四大组件都用到了,把基本用法复习了一遍,温故知新.

  • 相关阅读:
    Android 监听键盘弹出/隐藏
    js 监听事件的叠加和移除
    如何用 Swift 语言构建一个自定控件
    适用于Web开发人员的20个CSS调色板
    学习Flutter应用开发有用的代码/库/专有技术列表
    学习Java的书籍资料
    可能对Flutter应用程序开发有用的代码/库/专有技术列表
    ios 动画:底部标签栏的概念设计
    iOS 开发者必不可少的 75 个工具
    创建Android Apps的30个经验教训
  • 原文地址:https://www.cnblogs.com/happyhacking/p/5264168.html
Copyright © 2011-2022 走看看