android版天气预报程序开发总结

一,开发中所涉及到的技术概括:

tabhost选项卡组件,pagerAdapter左右滑屏的实现,json数据解析,xml数据解析,ListActivity与BaseAdapter的结合实现数据和图片的列表显示,handler更新UI,单例模式实现在整个project下数据的共享,httpClient访问网络,sqlite轻量级数据库的运用

二,程序运行效果展示:

主页



三,关键代码注解:

1.tabhost组件运用:

布局文件代码如下

<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/tabhost"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" 
 >

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
         android:background="@drawable/yun4"
        android:orientation="vertical" >

	<RelativeLayout
	    xmlns:android="http://schemas.android.com/apk/res/android"
	    android:id="@+id/biaotouFramelayout"
	    android:layout_width="fill_parent"
	    android:layout_height="64dp" >

	    <!--
	     <ImageButton
	         android:id="@+id/shuaxinButton"
	         android:layout_width="wrap_content"
	         android:layout_height="wrap_content"
	         android:layout_gravity="right"
	         android:layout_marginTop="10dp"
	         android:src="@drawable/shuaxin" />
	    -->

	    <ImageView
	        android:id="@+id/imageView5"
	        android:layout_width="53dp"
	        android:layout_height="65dp"
	        android:src="@drawable/weather" />

	    <TextView
	        android:id="@+id/title_textview"
	        style="@style/activity_title_text"
	        android:layout_width="wrap_content"
	        android:layout_centerHorizontal="true"
	        android:layout_centerVertical="true" />

	    <ImageButton
	        android:id="@+id/shuaxinImageBtn"
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	        android:layout_alignParentBottom="true"
	        android:layout_alignParentRight="true"
	        android:layout_alignParentTop="true"
	        android:src="@drawable/shuaxin" />

	</RelativeLayout>

        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_weight="1" 
           >
        </FrameLayout>
        
        <TabWidget
             android:id="@android:id/tabs"
              android:layout_width="fill_parent"  
            android:layout_height="wrap_content"  
            android:paddingLeft="1dip"  
            android:visibility="gone"  />
   
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="53dp"
          
            android:paddingTop="5dip" >

            <LinearLayout
                android:id="@+id/channel1"
                style="@style/main_tab_but_linear" >

                <ImageView
                    android:id="@+id/imageView1"
                    android:layout_width="wrap_content"
                    android:layout_height="54dp"
                    android:src="@drawable/tianqi" />

                <TextView
                    android:id="@+id/textView1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:text="1" />
            </LinearLayout>

            <LinearLayout
                android:id="@+id/channel2"
                style="@style/main_tab_but_linear" >

                <ImageView
                    android:id="@+id/imageView2"
                    android:layout_width="wrap_content"
                    android:layout_height="52dp"
                    android:src="@drawable/qushi" />

                <TextView
                    android:id="@+id/textView2"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:text="2" />
            </LinearLayout>

            <LinearLayout
                android:id="@+id/channel3"
                style="@style/main_tab_but_linear"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_weight="1"
                android:orientation="vertical" >

                <ImageView
                    android:id="@+id/imageView3"
                    android:layout_width="wrap_content"
                    android:layout_height="52dp"
                    android:src="@drawable/shezhi" />
            </LinearLayout>

            <LinearLayout
                android:id="@+id/channel4"
                style="@style/main_tab_but_linear"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_weight="1"
                android:orientation="vertical" >

                <ImageView
                    android:id="@+id/imageView4"
                    android:layout_width="fill_parent"
                    android:layout_height="54dp"
                    android:src="@drawable/gengduo" />

                <TextView
                    android:id="@+id/textView4"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:text="4" />
            </LinearLayout>

          
        </LinearLayout>
        
        
    </LinearLayout>

</TabHost>

a.使用tabhost的activity需要继承TabActivity,调用getTabHost()获取tabhost对象。

  b. 使用tabhost选项卡实现按钮处透明化方法 tabHost
.newTabSpec(tagName)
.setIndicator(getResources().getString(tagLable),
getResources().getDrawable(icon)).setContent(content);   setIndicator()方法用来设置选项卡tab按钮的背景以及文字,添加透明背景的TextView对象即可实现按钮背景的透明。

2. xml解析,包括读取,删除,写入数据

自定义的xml格式如下:

<?xml version="1.0" encoding="GB2312"?>
-<city> <item>如皋</item> <item>沈阳</item><item>长沙</item><item>武汉</item></city>
public class XMLManager {
	private Context context;
	DocumentBuilderFactory docBuilderFactory = null;
	DocumentBuilder docBuilder = null;
	Document doc = null;
	File file = new File(Environment.getExternalStorageDirectory()
			+ File.separator + "citydata" + File.separator + "city.xml");// 要输出文件的路径

	public XMLManager(Context context) {
		this.context = context;
		docBuilderFactory = DocumentBuilderFactory.newInstance();
		try {
			docBuilder = docBuilderFactory.newDocumentBuilder();

			doc = docBuilder.parse(new BufferedInputStream(new FileInputStream(
					file)));
			doc.normalize();
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// xml file 放到 assets目录中的

	}

	public void ReadXML() {

		// root element
		Element root = doc.getDocumentElement();
		NodeList nodeList = root.getElementsByTagName("item");
		Log.i("nodesize", String.valueOf(root.getChildNodes().getLength()));
		for (int i = 0; i < nodeList.getLength(); i++) {
			Element nd = (Element) nodeList.item(i);
			Log.i("node", nd.getFirstChild().getNodeValue());
			CityDataManager.getInstance()
					.add(nd.getFirstChild().getNodeValue());
		}
		Log.i("node",
				String.valueOf(CityDataManager.getInstance().getItems().size()));
	}

	public void removeItem(String name) {
		Element root = (Element) (doc.getDocumentElement()
				.getElementsByTagName("city").item(0));
		Log.i("node cityname", name);
		for (int i = 0; i < root.getElementsByTagName("item").getLength(); i++) {
			Element e = (Element) root.getElementsByTagName("item").item(i);
			Log.i("node vlaue", e.getFirstChild().getNodeValue());
			if (e.getFirstChild().getNodeValue().equals(name)) {
				if (root.removeChild(e) != null)
					save();
			}
		}
	}

	public void addItem(String name) {
		Element root = (Element) (doc.getDocumentElement()
				.getElementsByTagName("city").item(0));
		Log.i("root",
				String.valueOf(root.getElementsByTagName("item").getLength()));
		Element citynode = doc.createElement("item");
		citynode.appendChild(doc.createTextNode(name));
		// citynode.setNodeValue("北京");

		root.appendChild(citynode);
		Log.i("root",
				String.valueOf(root.getElementsByTagName("item").getLength()));

		save();

	}

	private void save() {
		if (!Environment.getExternalStorageState().equals(
				Environment.MEDIA_MOUNTED)) {// sdcard不存在
			return;// 返回程序被调用处
		}
		File file = new File(Environment.getExternalStorageDirectory()
				+ File.separator + "citydata" + File.separator + "city.xml");// 要输出文件的路径

		if (!file.getParentFile().exists()) {// 父路径不存在
			file.getParentFile().mkdirs();// 创建父文件夹

		}

		TransformerFactory tFactory = TransformerFactory.newInstance();
		Transformer transformer = null;

		try {
			transformer = tFactory.newTransformer();
		} catch (TransformerConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		transformer.setOutputProperty(OutputKeys.ENCODING, "GB2312");
		DOMSource source = new DOMSource(doc);
		StreamResult result = new StreamResult(file);

		try {
			transformer.transform(source, result);
		} catch (TransformerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

3.android平台的sqlite数据库的应用:

public class DBManager {

	public static final String _DB_PATH = "/data/data/com.android.weather/databases";
	// private final int BUFFER_SIZE = 400000;
	public static final String DB_NAME = "db_weather.db"; // 保存的数据库文件名
	public static final String PACKAGE_NAME = "com.android.weather";
	public static final String DB_PATH = "/data"
			+ Environment.getDataDirectory().getAbsolutePath() + "/"
			+ PACKAGE_NAME; // 在手机里存放数据库的位置(/data/data/com.cssystem.activity/cssystem.db)

	private SQLiteDatabase database;
	private Context context;

	public DBManager(Context context) {
		this.context = context;
	}

	public SQLiteDatabase getDatabase() {
		return database;
	}

	public void setDatabase(SQLiteDatabase database) {
		this.database = database;
	}

	public void openDatabase() {
		System.out.println(DB_PATH + "/" + DB_NAME);
		this.database = this.openDatabase(DB_PATH + "/" + DB_NAME);
	}

	private SQLiteDatabase openDatabase(String dbfile) {

		try {
			if (!(new File(dbfile).exists())) {
				// 判断数据库文件是否存在,若不存在则执行导入,否则直接打开数据库
				InputStream is = this.context.getResources().openRawResource(
						R.raw.db_weather); // 欲导入的数据库
				FileOutputStream fos = new FileOutputStream(dbfile);
				byte[] buffer = new byte[is.available()];
				int count = 0;
				while ((count = is.read(buffer)) > 0) {
					fos.write(buffer, 0, count);
				}
				fos.close();
				is.close();
			}

			SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbfile,
					null);
			return db;

		} catch (FileNotFoundException e) {
			Log.e("Database", "File not found");
			e.printStackTrace();
		} catch (IOException e) {
			Log.e("Database", "IO exception");
			e.printStackTrace();
		}
		return null;
	}

	public void closeDatabase() {
		this.database.close();
	}

	public String getCityCodeByName(String cityName) {
		Cursor cursor = database.query("cities", new String[] { "city_num" },
				"name = ?", new String[] { cityName }, null, null, null);
		String cityCode = null;
		if (!cursor.isLast()) {
			cursor.moveToNext();
			cityCode = cursor.getString(0);
		}
		cursor.close();
		// database.close();
		return cityCode;
	}

}

4. 使用pagerView实现左右滑屏

布局文件代码

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"  
    android:orientation="vertical"
    android:theme="@android:style/Theme.Translucent"  >  
  
    <android.support.v4.view.ViewPager  
        android:id="@+id/viewPager"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content" />  
  
    <RelativeLayout  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:orientation="vertical" 
        >  
  
        <LinearLayout  
            android:id="@+id/viewGroup"  
            android:layout_width="fill_parent"  
            android:layout_height="wrap_content"  
            android:layout_alignParentBottom="true"  
            android:layout_marginBottom="30dp"  
            android:gravity="center_horizontal"  
            android:orientation="horizontal" >  
        </LinearLayout>  
    </RelativeLayout>  
  
</FrameLayout>  

activity的调用:
main = (ViewGroup) inflater.inflate(R.layout.circle_viewflow_layout,
				null);
		group = (ViewGroup) main.findViewById(R.id.viewGroup);
		viewPager = (ViewPager) main.findViewById(R.id.viewPager);
通过list<View>数组添加要加载的view,然后将此数组添加到继承了PagerAdapter的Myadatper中

MyAdapter myadapter = new MyAdapter(list, WeatherMainActivity.this,
				inflater, viewPager);
		MySingleInstance.getInstance().setMyadapter(myadapter);
		viewPager.setAdapter(myadapter);

		createDot();
		MyDotHandler dotHandler = new MyDotHandler();
		HandlerApp.getInstance().setDotHandler(dotHandler);
注:在adatper适配器中最好自定义一个List数组,更新数据后调用以下方法,更新UI。

MySingleInstance.getInstance().getMyadapter().notifyDataSetChanged();

5. handler的使用更新UI

自定义Handler

	public class MyHandler extends Handler {
		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			if (msg.what == CHANGED) { // 更新UI
				mListAdapter = new MyListAdapter(MoreActivity.this,
						CityListItemsDataManager.getInstance().getListData());
				setListAdapter(mListAdapter);
			}
		}
	}

在activity 实例化Handler

protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		instance = this;
		Log.i("listadapter",
				String.valueOf(CityListItemsDataManager.getInstance()
						.getListData().size()));
		mListAdapter = new MyListAdapter(this, CityListItemsDataManager
				.getInstance().getListData());
		setListAdapter(mListAdapter);

		mHandler = new MyHandler();
		HandlerApp.getInstance().setMyHandler(mHandler);

	}
更新数据后,需要取得实例化的Handler对象发送CHANGE消息,才能调用handler中方法,从而实现UI更新
HandlerApp.getInstance().getDotHandler().sendEmptyMessage(CHANGED);

源码下载地址: 点击打开链接
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值