Nội dung:
- threads
- files
- adapter
- intents
------------------------
1. Xử lý đa tiến trình bằng AsyncTask:
- Lớp AsyncTask được cung cấp sẵn trong android, lớp này hoạt động như một thread riêng biệt chạy gầm và không cần đồng bộ với các thread khác.
- Danh sách các hàm trong lớp AsyncTask và cách thức hoạt động:
- Giải thích các thông số trong lớp AsyncTask<Params, Progress, Result>
 + Params: biến này được truyền vào hàm doInBackground().
 + Progress: biến này được truyền vào hàm onProgressUpdate().
 + Result: biến này dùng để lưu kết quả trả về khi tiến trình thực hiện xong.
 Lưu ý: Các đối số không sử dụng trong quá trình thực thi AsyncTask thì thay bằng Void.

- Giải thích cách hoạt động của các hàm trong lớp AsyncTask:
 + onPreExecute(): tự động được gọi lần đầu tiên khi tiến trình được thực thi.
 + doInBackground(Params ...): được thực thi trong quá trình chạy nền sau khi hàm onPreExecute() chạy xong. Thông qua hàm này để gọi hàm onProgressUpdate() để cập nhật giao diện (gọi publishProgress). Các tham số Params được truyền vào hàm này.
 + onProgressUpdate(Progress...): Dùng để cập nhật giao diện lúc runtime.
 + onPostExecute(Result...): Sau khi tiến trình kết thúc thì hàm này sẽ được gọi.

Ví dụ sử dụng lớp AsyncTask để cập nhật cho ProgressBar :
Outline:
Mã nguồn java:
- Tạo lớp MyAsyncTask.java kế thừa từ lớp AsyncTask
- Và lớp MainActivity.java
MyAsyncTask.java:
package com.asynctask;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.SystemClock;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.asynctask.R;

public class MyAsyncTask extends AsyncTask<Void, Integer, Void> {
       Activity contextMain;
      
       public MyAsyncTask(Activity _context) {
              contextMain = _context;
       }

       @Override
       protected void onPreExecute() {
              super.onPreExecute();
       }

       @Override
       protected Void doInBackground(Void... params) {
              for(int i = 0; i <= 100; i++) {
                 SystemClock.sleep(100);
                 publishProgress(i); //khi gọi hàm này thì onProgressUpdate sẽ thực thi
              }
              return null;
       }
      
       @Override
       protected void onProgressUpdate(Integer... values) {
              super.onProgressUpdate(values);
              ProgressBar progressbar = (ProgressBar)
                                          contextMain.findViewById(R.id.progressBar1);
              int value = values[0];
                    
              progressbar.setProgress(value);
             
              TextView tv_status = (TextView) contextMain.findViewById(R.id.textView);
              tv_status.setText(value + " %");
       }

       @Override
       protected void onPostExecute(Void result) {
              super.onPostExecute(result);
       }
}

MainActivity.java:
public class MainActivity extends Activity {
      //...
       @Override
       protected void onCreate(Bundle savedInstanceState) {
             //...
              MyAsyncTask myasynctask = new MyAsyncTask(MainActivity.this);
              myasynctask.execute();
       }
      //...
}

Link download bài này: https://drive.google.com/file/d/0B8tAQ0_sJKCSUExaZlJKWlZPRWM/view?usp=sharing

Ví dụ demo cách sử dụng truyền danh sách tham số cho hàm thông qua dấu ... còn gọi là varargs (variable arguments), viết hàm tính tổng các danh sách số nguyên truyền vào hàm:
public class TinhTong {
       public static void main(String args[]) {
              System.out.println(TinhTong(1, 2, 3, 4));
              System.out.println(TinhTong(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
       }
      
       public static int TinhTong(int ...danhsach) {
              int sum = 0;
              for(int i : danhsach) {//danhsach.length()
                     sum += i;
              }
              return sum;
       }
}

2. Files:
Hướng dẫn lưu vào SDCard:
private static final String FILE_NAME = "/contacts.xml";

private void saveDataToSDCard() {
     Log.i("Save to SDCard","Path: " + Environment.getExternalStorageDirectory().
                                                  getAbsolutePath() + FILE_NAME);
      try {
       File myFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + FILE_NAME);
       if (!myFile.exists()) {
              myFile.createNewFile();
       }
       FileOutputStream os = new FileOutputStream(myFile);
       OutputStreamWriter myOutWriter = new OutputStreamWriter(os);
       myOutWriter.append("<?xml version=\"1.0\" encoding=\"utf-8\"?><contacts>");
             
       for (Person person : personArray) {
              myOutWriter.append("<contact><name>" + person.GetName()
                            + "</name><phone>" + person.GetPhone()
                            + "</phone></contact>");
       }
       myOutWriter.append("</contacts>");
       myOutWriter.close();
       os.close();
    } catch (Exception e) {
      Toast.makeText(getBaseContext(), e.getMessage(),
                                          Toast.LENGTH_SHORT).show();
   }
}

Load file contacts.xml:
private void loadDataFromSDCard() {
       try {
              File myFile = new File(Environment.getExternalStorageDirectory().
                                                        getAbsolutePath() + FILE_NAME);
              if (!myFile.exists()) {
                     Log.i("ContactList","File khong ton tai!");
                     return;
              }
              FileInputStream is = new FileInputStream(myFile);
              DocumentBuilder builder =
                        DocumentBuilderFactory.newInstance().newDocumentBuilder();
              Document doc = builder.parse(is);
              Element root = doc.getDocumentElement();
              NodeList items = root.getElementsByTagName("contact");
             
              for (int i = 0; i < items.getLength(); i++) {
                     Person person = new Person();
                     Node item = items.item(i);
                     NodeList properties = item.getChildNodes();
                     for (int j = 0; j < properties.getLength(); j++) {
                         Node property = properties.item(j);
                         String name = property.getNodeName();
                         if (name.equalsIgnoreCase("name")) {
                           person.SetName(property.getFirstChild().getNodeValue());
                         } else if (name.equalsIgnoreCase("phone")) {
                           person.SetPhone(property.getFirstChild()
                                                .getNodeValue());
                          }
                     }
                     personArray.add(person);
              }
              is.close();
       } catch (Exception e) {
         Toast.makeText(getBaseContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
       }
}

3. Use Adapter to display data in a list view:
- Để hiển thị dữ liệu dạng danh sách theo chiều dọc người ta thường sử dụng ListView.
- Adapter như là một cầu nối giữa dữ liệu (DataSource) và AdapterView (như ListView, ...)
Các bước để đưa dữ liệu DataSource vào Adapter, sau đó đưa Adapter vào ListView để hiển thị:
1. Get listview object from xml
   myListView = (ListView) findViewById(R.id.listView);
             
2. Define Array values to show in listview
   final ArrayList<String> myContact = new ArrayList<String>();
   myContact.add("Bánh tráng thịt heo");
   myContact.add("Mì quảng");
   myContact.add("Bê thui cầu mống");
             
3. Define a new Adapter
   ArrayAdapter myAdapter = new ArrayAdapter<String>(this,
                                android.R.layout.simple_list_item_1, myContact);
             
4. Assign adapter to listview
   myListView.setAdapter(myAdapter);
             
5. Set listview listerner
   myListView.setOnItemClickListener(this);

Các bước xử lý sự kiện với Adapter:

Ví dụ 1: Dùng Adapter và ListView hiển thị danh sách các món ăn như hình sau
Mã nguồn:
Thiết kế giao diện:
Mã nguồn java:
package com.adapter;

import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

public class MainActivity extends Activity implements OnItemClickListener {
       ListView myListView;
       ArrayAdapter<String> myAdapter;
      
       @Override
       protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
              //1. Get listview object from xml
              myListView = (ListView) findViewById(R.id.listView);
             
              //2. Define Array values to show in listview
              final ArrayList<String> myContact = new ArrayList<String>();
              myContact.add("Bánh tráng thịt heo");
              myContact.add("Mì quảng");
              myContact.add("Bê thui cầu mống");
             
              //3. Define a new Adapter
              myAdapter = new ArrayAdapter<String>(this,
                              android.R.layout.simple_list_item_1, myContact);
             
              //4. Assign adapter to listview
              myListView.setAdapter(myAdapter);
             
              //5. Set listview listerner
              myListView.setOnItemClickListener(this);
       }
      
       @Override
       public void onItemClick(AdapterView<?> arg0, View arg1, 
                                          int arg2, long arg3) {
              // ...
              Toast.makeText(MainActivity.this,
                       myListView.getItemAtPosition(arg2).toString(), 
                       Toast.LENGTH_LONG).show();
       }
      // ...
}

Download mã nguồn:

Ví dụ 2: Hiển thị danh sách danh bạ điện thoại gồm 2 phần tên và số điện thoại. Trong ví dụ này dùng kỹ thuật custom layout ListView để cho phù hợp.
Cấu trúc dự án:

Thiết kế layout:
- Trong thư mục layout: thêm list_item.xml dùng để Custom layout lại ListView:
Tệp tin list_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="5dp" >

    <TextView
        android:id="@+id/tvName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:textSize="20dp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/tvPhone"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_toRightOf="@id/tvName"
        android:textSize="20dp"
        android:gravity="right"/>

</RelativeLayout>

Mã nguồn java:

Trong đó:
- Class Person dùng để lưu trữ thông tin người: họ tên và số phone. - Class MyArrayAdapter kế thừa từ ArrayAdapter mục đích của nó là giúp chúng ta Custom lại layout cho ListView.
Mã nguồn lớp Person:
public class Person {
       private String name;
       private String phone;

       public Person(String name, String phone) {
              super();
              this.name = name;
              this.phone = phone;
       }
       public String getName() {
              return name;
       }
       public void setName(String name) {
              this.name = name;
       }
       public String getPhone() {
              return phone;
       }
       public void setPhone(String phone) {
              this.phone = phone;
       }
}

Mã nguồn lớp MyArrayAdapter:
public class MyArrayAdapter extends ArrayAdapter<Person> {
       public MyArrayAdapter(Context context, int resourceID, List<Person> objects) {
              super(context, resourceID, objects);
       }
      
       @Override
       public View getView(int position, View convertView, ViewGroup parent) {
              // Get the data item for this position
              Person person = getItem(position);
              // Check if an existing view is being reused, otherwise inflate the view
              if (convertView == null) {
                     convertView = LayoutInflater.from(getContext()).inflate(
                                           R.layout.list_item, parent, false);
              }
              // Lookup view for data population
              TextView tvName = (TextView) convertView.findViewById(R.id.tvName);
              TextView tvPhone = (TextView) convertView.findViewById(R.id.tvPhone);
              // Populate the data into the template view using the data object
              tvName.setText(person.getName());
              tvPhone.setText(person.getPhone());
             
              // Return the completed view to render on screen
              return convertView;
       }
}

Mã nguồn  MainActivity:
public class MainActivity extends Activity implements OnItemClickListener {

       private ListView myListView;
       private MyArrayAdapter myAdapter;
             
       @Override
       public void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
              myListView = (ListView) findViewById(R.id.myListView);
             
              // create ArrayList
              ArrayList<Person> personArray = new ArrayList<Person>();
              personArray.add(new Person("Nguyen Van A", "0905123456"));
              personArray.add(new Person("Nguyen Van B", "0943546366"));
              personArray.add(new Person("Nguyen Van C", "0934564566"));
              personArray.add(new Person("Nguyen Van D", "0913242335"));
             
              // create an instance of MyArrayAdapter
              myAdapter = new MyArrayAdapter(this, R.layout.list_item, personArray);
                                          // lấy custom layout, thiết lập data source
             
              myListView.setAdapter(myAdapter);//gán Adapter vào Lisview
              myListView.setOnItemClickListener(this);
       }

       @Override
       public void onItemClick(AdapterView<?> arg0, View v, int pos, long id) {
              Person ps = myAdapter.getItem(pos);
              ps.setName("Nguyen Van Z");
              myAdapter.notifyDataSetChanged();       
       }
}

Download mã nguồn:

Ví dụ 3: Hiển thị danh sách việc làm như sau
Cấu trúc dự án:

Thiết kế layout:
- Trong thư mục layout: thêm customlayout_listview.xml dùng để Custom layout lại ListView:
Tệp tin customlayout_listview.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:orientation="vertical" >

    <CheckBox
       android:id="@+id/checkbox"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:gravity="center_vertical"
       android:textSize="18sp" />

</LinearLayout>

Mã nguồn java:

Trong đó:
- Class MyArrayAdapter kế thừa từ ArrayAdapter mục đích của nó là giúp chúng ta Custom lại layout cho ListView.

Mã nguồn lớp MyArrayAdapter:
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.Toast;

public class MyArrayAdapter extends ArrayAdapter<String> implements OnCheckedChangeListener{
       private ArrayList<CheckBox> selected;//để lưu các checkbox được chọn
       private CheckBox chkName;
       public MyArrayAdapter(Context context, int resourceID,
                                              List<String> objects)
       {
              super(context, resourceID, objects);
              selected = new ArrayList<CheckBox>();
       }

       @Override
       public View getView(int position, View convertView, ViewGroup parent) {
           if (convertView == null) {
                convertView = LayoutInflater.from(getContext()).inflate(
                                R.layout.customlayout_listview, parent, false);
           } 

          chkName = (CheckBox) convertView.findViewById(R.id.checkbox);
          chkName.setText(getItem(position));
          chkName.setOnCheckedChangeListener(this);
          return convertView;
       }

       public ArrayList<CheckBox> getSelected() {
              return selected;
       }

       @Override
       public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
       {
              CheckBox checkbox = (CheckBox)buttonView;
              if (isChecked) {
                     selected.add(checkbox);//checkbox nào chọn add vào selected
                     //Toast.makeText(getContext(), buttonView.getText(),
                                                     Toast.LENGTH_SHORT).show();
              } else {
                     selected.remove(checkbox);
              }
       }
}

Mã nguồn  MainActivity:
import android.app.Activity;
import android.os.Bundle;
import java.util.ArrayList;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener {
       private ListView lstListView;
       private MyArrayAdapter myAdapter;
       private Button btnSend;

       @Override
       public void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);

              btnSend = (Button) findViewById(R.id.btnSend);

              lstListView = (ListView) findViewById(R.id.listview);
              ArrayList<String> myStringArray = new ArrayList<String>();
              myStringArray.add("Lập trình Android");
              myStringArray.add("Lập trình iOS");
              myStringArray.add("Mạng máy tính");
             
              myAdapter = new MyArrayAdapter(this,
                                 R.layout.customlayout_listview, myStringArray);
              lstListView.setAdapter(myAdapter);
              btnSend.setOnClickListener(this);
       }

       @Override
       public void onClick(View v) {
              if (v.getId() == R.id.btnSend) {
                     String strSelect = "";
                     for (int i = 0; i < myAdapter.getSelected().size(); i++) {
                           strSelect += myAdapter.getSelected().get(i).getText();
                     }
                     Toast.makeText(this, strSelect, Toast.LENGTH_SHORT).show();
              }
       }
}

Download mã nguồn:

4. Intents:

- Giới thiệu Intents là thành phần quan trọng trong android, trong giới hạn bài này sẽ giới thiệu chức năng của Intents sẽ mở một Activity khác và truyền dữ liệu qua lại giữa các Activity này (truyền qua và nhận giá trị trả về). Download ví dụ này link: https://drive.google.com/file/d/0B8tAQ0_sJKCSbTE2MlBuelNocnc/view?usp=sharing

- Các bước sau đây thực hiện việc mở và truyền dữ liệu qua lại giữa các Activity dùng Intents:
- Sử dụng Intent để mở một Activity khác:
Ví dụ có 2 activity: MainActivity OtherActivity, các bước để từ MainActivity mở OtherActivity:
Bước 1. Code java trong MainActivity.java
//create the intent
Intent intent = new Intent(MainActivity.thisOtherActivity.class);
                        
//start the intent
this.startActivity(intent);

Bước 2. Trong tệp tin AndroidManifest.xml thêm:
<activity
        android:name=".OtherActivity">           
</activity>

Bước 3: OtherActivity.java
protected void onCreate(Bundle savedInstanceState) {
       //...
       setContentView(R.layout.activity_other);//Layout cần mở
}

- Sử dụng Intent để mở một Activity khác và kiểm soát kết quả trả về:
Ví dụ có 2 activity: MainActivity và OtherActivity
Bước 1: MainActivity.java
//1. create the intent
Intent intent = new Intent(MainActivity.this, OtherActivity.class);

//2. put data in the intent
  //Cách 1: put từng giá trị vào intent dựa vào mã key để qua bên OtherActivity nhận
    intent.putExtra("key_1", value1);//value1 là giá trị cần chuyển đi
    intent.putExtra("key_2", value2);//value2 là giá trị cần chuyển đi

  //Cách 2: dùng Bundle-như một một kiện hàng container-chứa các gói kiện hàng nhỏ
    rồi chuyển đi một lần
    Bundle bundle = new Bundle();
    bundle.putXXX("key_1", value1);
    bundle.putXXX("key_2", value2);
    intent.putExtra("key_package", bundle);//Gởi kiện hàng bundle (container lớn) đi

   //Cách 3: để đưa 1 đối tượng vào Bundle
    Objects object = new Objects();//Objects là một class
    bundle.putSerializable("key_object", object);

//3. start the intent
    //Dùng hàm này startActivityForResult để đợi nhận giá trị trả về tử OtherActivity
    this.startActivityForResult(intent, REQUEST_CODE);//REQUEST_CODE là một hằng kiểu nguyên
    //Dùng hàm này không đợt nhận kết quả trả về
    this.startActivity(intent);

//4. Function receive data from OtherActivity
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
       super.onActivityResult(requestCode, resultCode, data);
       if (requestCode == REQUEST_CODE) {
              switch(resultCode) {
                     case RESULT_DATA1://lấy giá trị ra
                          
                           break;
                     case RESULT_DATA2:
                           break;                    
              }
       }
    }

Bước 2: OtherActivity.java
Intent data = new Intent();
data.putExtra("Key_1", value1_return);
data.putExtra("Key_2"value2_return);
setResult(RESULT_DATA1, data);//Send dữ liệu
finish();//Đóng Activity

Ví dụ: Xây dựng ứng dụng lưu trữ danh bạ điện thoại như hình sau
Lưu ý bài này làm tiếp từ bài ví dụ 2 ở trên
Mã nguồn:
Bố cục dự án:

Layout: thiết kế thêm activity_add.xml

Trong tệp tin AndroidManifest.xml thêm:
<activity
        android:name=".AddActivity">           
</activity>

Mã nguồn java:
MainActivity.java:
public class MainActivity extends Activity {
       public static final int REQUEST_CODE_ADD = 100;
       //...
       public void onClickAdd(View v) {
              //create the intent
              Intent intent = new Intent(MainActivity.this,
                                         AddActivity.class);         
              this.startActivityForResult(intent, REQUEST_CODE_ADD);
       }
       //Hàm này để đợi nhận kết quả về
       @Override
       protected void onActivityResult(int requestCode, int resultCode, Intent data)
       {
              super.onActivityResult(requestCode, resultCode, data);
              if (requestCode == REQUEST_CODE_ADD) {
                     switch(resultCode) {
                           case RESULT_OK:
                                  String name = data.getStringExtra("key_name");
                                  String phone = data.getStringExtra("key_phone");
                                  personArray.add(new Person(name, phone));
                                  myAdapter.notifyDataSetChanged();
                                  break;
                     }
              }
       }
       //...
}

AddActivity.java:
package com.contactlist;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;

public class AddActivity extends Activity {
       EditText edtName, edtPhone;
      
       @Override
       protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_add);
              edtName = (EditText) findViewById(R.id.edtName);
              edtPhone = (EditText) findViewById(R.id.edtPhone);
       }
       //Hàm onClikSave bên XML code
       public void onClickSave(View v) {
              Intent data = new Intent();
              data.putExtra("key_name", edtName.getText().toString().trim());
              data.putExtra("key_phone", edtPhone.getText().toString().trim());
              setResult(RESULT_OK, data);//send data
              finish();
       }
}

Link download bài danh bạ điện thoại:
https://drive.google.com/file/d/0B8tAQ0_sJKCSZVVQOVptWmwyU2s/view?usp=sharing


Bài tập:
1. Xây dựng ứng dụng thời tiết
Bài giải:
Bố cục dự án:

Thiết kế layout:
+list_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/AbsoluteLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:ignore="HardcodedText" >

    <ImageView
        android:id="@+id/imageViewIcon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/sunny" />

    <TextView
        android:id="@+id/tvNameCity"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_x="78dp"
        android:layout_y="7dp"
        android:text="DaNang"
        android:textSize="20sp"
        tools:ignore="HardcodedText" />

    <TextView
        android:id="@+id/tvWeather"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_x="88dp"
        android:layout_y="47dp"
        android:text="@string/sunny"
        android:textSize="15sp" />

    <TextView
        android:id="@+id/tvTemperature"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_x="218dp"
        android:layout_y="23dp"
        android:text="32°C"
        android:textSize="25sp" />

</AbsoluteLayout>

+activity_main.xml:
<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.weather.MainActivity" >

    <ListView
        android:id="@+id/mylistView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true" >
    </ListView>

</RelativeLayout>

Mã nguồn JavaWeather.java, MyArrayAdapter.java, MainActivity.java
+ Weather.java:
package com.weather;

public class Weather {
       private String pathImage, cityName, weather, temperature;
      
       public Weather() {
             
       }
      
       public Weather(String _cityName, String _weather, String _temperature, String _pathImage) {
              this.cityName = _cityName;
              this.weather = _weather;
              this.temperature = _temperature;
              this.pathImage = _pathImage;
       }
      
       public String getPathImage() {
              return pathImage;
       }
       public void setPathImage(String pathImage) {
              this.pathImage = pathImage;
       }
       public String getCityName() {
              return cityName;
       }
       public void setCityName(String cityName) {
              this.cityName = cityName;
       }
       public String getWeather() {
              return weather;
       }
       public void setWeather(String weather) {
              this.weather = weather;
       }
       public String getTemperature() {
              return temperature;
       }
       public void setTemperature(String temperature) {
              this.temperature = temperature;
       }     
}

+ MyArrayAdapter.java:

package com.weather;

import java.util.List;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class MyArrayAdapter extends ArrayAdapter<Weather> {

       public MyArrayAdapter(Context context, int textViewResourceId, List<Weather> objects) {
              super(context, textViewResourceId, objects);
             
       }
      
       @Override
       public View getView(int position, View convertView, ViewGroup parent) {
              Weather weather = getItem(position);
             
              if(convertView == null) {
                     convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item, parent, false);
              }
             
              TextView tvNameCity = (TextView) convertView.findViewById(R.id.tvNameCity);
              TextView tvWeather = (TextView) convertView.findViewById(R.id.tvWeather);
              TextView tvTemperature = (TextView) convertView.findViewById(R.id.tvTemperature);
              ImageView imageviewIcon = (ImageView) convertView.findViewById(R.id.imageViewIcon);
             
              tvNameCity.setText(weather.getCityName());
              tvWeather.setText(weather.getWeather());
              tvTemperature.setText(weather.getTemperature());
             
              String uri = "drawable/" + weather.getPathImage();
              int imageResource = convertView.getContext().getApplicationContext().getResources().getIdentifier(uri, null, convertView.getContext().getApplicationContext().getPackageName());
              Drawable res = convertView.getContext().getResources().getDrawable(imageResource);
              imageviewIcon.setImageDrawable(res);
             
              return convertView;
       }     
}

+ MainActivity.java:
package com.weather;

import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView;

public class MainActivity extends Activity {
       private ListView myListView;
       private MyArrayAdapter myAdapter;
      
       @Override
       protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
             
              myListView = (ListView) findViewById(R.id.mylistView);
              //create ArrayList
              ArrayList<Weather> weatherArray = new ArrayList<Weather>();
              weatherArray.add(new Weather("Ha Noi", "Sunny", "32°C", "sunny"));
              weatherArray.add(new Weather("Quang Binh", "Cloudy", "25°C", "cloudy"));
              weatherArray.add(new Weather("Hue", "Rainy", "23°C", "rainy"));
              weatherArray.add(new Weather("Da Nang", "Sunny", "32°C", "sunny"));
              weatherArray.add(new Weather("Quang Nam", "Sunny", "30°C", "sunny"));
             
              weatherArray.add(new Weather("Quang Ngai", "Thunder", "24°C", "thunder"));
              weatherArray.add(new Weather("Da Lat", "Cloudy", "20°C", "cloudy"));
              weatherArray.add(new Weather("Phan Thiet", "Thunder", "24°C", "thunder"));
              weatherArray.add(new Weather("Vung Tau", "Rainy", "25°C", "rainy"));
              weatherArray.add(new Weather("Ho Chinh Minh", "Sunny", "33°C", "sunny"));        
             
              //create adapter
              myAdapter = new MyArrayAdapter(MainActivity.this, R.layout.list_item, weatherArray);
             
              myListView.setAdapter(myAdapter);       
       }

       @Override
       public boolean onCreateOptionsMenu(Menu menu) {
              // Inflate the menu; this adds items to the action bar if it is present.
              getMenuInflater().inflate(R.menu.main, menu);
              return true;
       }

       @Override
       public boolean onOptionsItemSelected(MenuItem item) {
              // Handle action bar item clicks here. The action bar will
              // automatically handle clicks on the Home/Up button, so long
              // as you specify a parent activity in AndroidManifest.xml.
              int id = item.getItemId();
              if (id == R.id.action_settings) {
                     return true;
              }
              return super.onOptionsItemSelected(item);
       }
}

--> Có thể đọc data cho weatherArray từ json weather api. Xem tiếp ví dụ thời tiết lấy dữ liệu từ JSON ở bài số 11.
Link download bài này:
https://drive.google.com/file/d/0B8tAQ0_sJKCSUWI1MEZsZHJ3czA/view?usp=sharing


2.