본문 바로가기
프로그래밍/안드로이드

안드로이드 어싱크태스크(AsyncTask),로딩중 표시(ProgressDialog), 웹서버 연결 통신(HttpURLConnection)

by -현's- 2015. 5. 1.
반응형


●어싱크태스트(Async Task)

네트워크 연결이므로, 연결시에 지연이 발생할 수 있다. 따라서 메인쓰레드(UI쓰레드)로 네트워크 접속을 시도하면 앱은 접속이 성공되고 응답을 받을때까지 동작을 못하게 된다. 따라서 안드로이드 최근버전부터는 메인쓰레드가 네트워크 접속을 시도하는것 자체를 금지한다.


웹서버로부터 데이터를 가져와서 ListView 등에 출력하려면 동생쓰레드에서 가져온 데이터를 UI에 반영하는 작업이 필요한데, 안드로이드에서는 개발자가 정의한 쓰레드는 UI를 제어할 수 없도록 금지시켜놓았다. 그래서 Handler를 사용해야 하는데 이 작업은 번거롭다.

그래서 AsyncTask라는 백그라운드 작업용 클래스를 지원하게 되었다.


- AsyncTask = Thread + Handler




●로딩중 표시(ProgressDialog)

AsyncTask클래스 안에서 onPreExecute()안에 로딩중 표시 다이얼로그를 보여주고 onPostExecute()에 로딩중 표시 다이얼로그를 제거해준다.






●웹서버 연결 통신(HttpURLConnection)

- 접속대상 서버주소를 URL클래스와 통신을 담당하는 HttpURLConnection클래스를 이용해서 웹서버에 데이터를 넘겨주고 받는다.


- Manifest.xml에 '<uses-permission android:name="android.permission.INTERNET"/>, <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>'을 추가한다.




●예제


 - WebConnectActivity.java

package com.example.day0425;


import android.app.Activity;

import android.content.Context;

import android.net.ConnectivityManager;

import android.net.NetworkInfo;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.ListView;

import android.widget.Toast;


public class WebConnectActivity extends Activity implements OnClickListener{

Button btn;

MyAsyncTask task;

ListView listView;

MyListAapter adapter;

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.webconnect);

listView = (ListView)findViewById(R.id.listView);

adapter = new MyListAapter(this);

listView.setAdapter(adapter);

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

btn.setOnClickListener(this);

}

//웹에서 데이터를 가져오기 전에 먼저 네트워크 상태부터 확인

public void conntectCheck(){

   ConnectivityManager connMgr = (ConnectivityManager) 

       getSystemService(Context.CONNECTIVITY_SERVICE);

   NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();

   if (networkInfo != null && networkInfo.isConnected()) {

       // fetch data

    //Toast.makeText(this,"네트워크 연결중입니다.", Toast.LENGTH_SHORT).show();

    task = new MyAsyncTask(this);

task.execute("");

   } else {

       // display error

    Toast.makeText(this,"네트워크 상태를 확인하십시오", Toast.LENGTH_SHORT).show();

   }

}

public void onClick(View v) {

conntectCheck();

}

}

 



- webconnect.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">

    

    <Button 

        android:id="@+id/btn"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="웹 연동 클릭"

        android:layout_gravity="center_horizontal"

        android:layout_marginTop="10dp"/>

    

    <ListView 

        android:id="@+id/listView"

        android:layout_width="match_parent"

        android:layout_height="match_parent">

    </ListView>

</LinearLayout>

 



- MyAsyncTask.java

package com.example.day0425;


import java.util.ArrayList;


import org.json.JSONArray;

import org.json.JSONException;

import org.json.JSONObject;


import android.app.ProgressDialog;

import android.content.Context;

import android.os.AsyncTask;

import android.widget.Toast;


/*

 * Params - 비동기 작업시 필요한 데이터 자료형

 * ex)웹사이트에 데이터 요청시 전송할 파라미터값(ID,PW 등....)

 * 

 * Progress - 비동기 방식의 요청이 진행될때 사용될 데이터 자료형.

 *  숫자형 자료형을 많이 사용한다.

 * 

 * Result - 웹서버로부터 가져오게 될 데이터에 알맞는 자료형을 개발자가 결정

 * 주로 JSON, XML등을 가져오게 되므로 String을 많이 사용한다.

 */

public class MyAsyncTask extends AsyncTask<String, Integer, String>{

WebConnectActivity context;

ProgressDialog dialog;

LoadManager load;//접속과 요청을 담당하는 객체 선언

public MyAsyncTask(Context context) {

this.context = (WebConnectActivity)context;

load = new LoadManager();

}

//백그라운드 작업 수행전에 해야할 업무등을 이 메서드에 작성하며 되는데,

//이 메서드는 UI쓰레드에 의해 작동하므로 UI를 제어할 수 있다.

//따라서 이 타이밍에 진행바를 보여주는 작업등을 할 수 있다.

protected void onPreExecute() {

super.onPreExecute();

dialog = new ProgressDialog(context);

//dialog.setCancelable(false);

dialog.show();

}

//비동기방식으로 작동할 메서드이며, 주로 메인쓰레드와는 별도로

//웹사이트의 연동이나 지연이 발생하는 용도로 사용하면 된다.

//사실상 개발자가 정의 쓰레드에서 run메서드와 비슷하다

//  'String...' 가변형 파라미터로 파라미터 개수 상관없이 넣을 수 있다.

protected String doInBackground(String... params) {

//웹서버에 요청시도

String data = load.request();

return data;

}

//백그라운드 메서드가 업무수행을 마칠때 호출되는 메서드.

//UI쓰레드에 의해 호출되므로, UI쓰레드를 제어할 수 있다.

//따라서 진행바를 그만 나오게 할 수 있다.

protected void onPostExecute(String result) {

super.onPostExecute(result);

dialog.dismiss();

Toast.makeText(context, result, Toast.LENGTH_SHORT).show();

System.out.println("a");

//최종적으로 웹서버로부터 데이터를 완전히 가져온 시점은 이 메서드이므로,

//어댑터가 보유한 ArrayList를 갱신시켜주자!

ArrayList<DataVo> dataList = context.adapter.lst;

dataList.removeAll(dataList);

try {

JSONObject o = new JSONObject(result);

//JSONArray array = new JSONArray(result);

JSONArray array = o.getJSONArray("a");

DataVo dataVo = null;

JSONObject obj = null;

System.out.println("1");

for(int i=0;i<array.length();i++){

obj = array.getJSONObject(i);

dataVo = new DataVo();


System.out.println("2obj.getString(name):"+obj.getString("name"));

dataVo.setName(obj.getString("name"));

dataVo.setAge(obj.getInt("age"));

dataVo.setIsBool(obj.getString("isBool"));

dataList.add(dataVo);


context.listView.invalidateViews();

}

System.out.println("3");

context.listView.invalidate();

System.out.println("array.length():"+array.length());

} catch (JSONException e) {

e.printStackTrace();

}

}

}





- LoadManager.java

package com.example.day0425;


import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.net.HttpURLConnection;

import java.net.MalformedURLException;

import java.net.URL;


public class LoadManager {

URL url; //접속대상 서버주소를 가진 객체

HttpURLConnection conn; //통신을 담당하는 객체

BufferedReader buffer=null;


//필요한 객체 초기화

public LoadManager() {

try {

url = new URL("http://192.168.0.18:8080/index2.jsp");

conn = (HttpURLConnection)url.openConnection();

} catch (MalformedURLException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

public String request(){

String data="";

try {

conn.connect(); //웹서버에 요청하는 시점

InputStream is = conn.getInputStream(); //웹서버로부터 전송받을 데이터에 대한 스트림 얻기

//1byte기반의 바이트스트림이므로 한글이 깨진다.

//따라서 버퍼처리된 문자기반의 스트림으로 업그레이드 해야 된다.

buffer = new BufferedReader(new InputStreamReader(is));

//스트림을 얻어왔으므로, 문자열로 반환

StringBuffer str = new StringBuffer();

String d=null;

while( (d=buffer.readLine()) != null){

str.append(d);

}

data = str.toString();

} catch (IOException e) {

e.printStackTrace();

} finally{

if(buffer!=null){

try {

buffer.close();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

return data;

}

}

 



- MyListAdapter.java

package com.example.day0425;


import java.util.ArrayList;

import android.content.Context;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.BaseAdapter;

import android.widget.TextView;


public class MyListAapter extends BaseAdapter{

ArrayList<DataVo> lst = new ArrayList<DataVo>();

Context context;

LayoutInflater infalter;

public MyListAapter(Context context) {

this.context = context;

infalter = (LayoutInflater)context.getSystemService(context.LAYOUT_INFLATER_SERVICE);

}

public int getCount() {

return lst.size();

}

public Object getItem(int arg0) {

return null;

}

public long getItemId(int arg0) {

return 0;

}

public View getView(int position, View convertView, ViewGroup parent) {

View view = null;

if(convertView==null){

view = infalter.inflate(R.layout.list_item, parent, false);

}else{

view = convertView;

}

TextView txt_name = (TextView)view.findViewById(R.id.txt_name);

TextView txt_age = (TextView)view.findViewById(R.id.txt_age);

TextView txt_bool = (TextView)view.findViewById(R.id.txt_bool);

DataVo dataVo = (DataVo)lst.get(position);

txt_name.setText(dataVo.getName());

txt_age.setText(Integer.toString(dataVo.getAge()));

txt_bool.setText(dataVo.getIsBool());

return view;

}

}

 



- list_item.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="horizontal" >

    

    <ImageView 

        android:id="@+id/imgView"

        android:layout_width="0dp"

        android:layout_height="45dp"

        android:layout_weight="1"

        android:src="@drawable/ic_launcher"/>

    <TextView 

        android:id="@+id/txt_name"

        android:layout_width="0dp"

        android:layout_height="45dp"

        android:layout_weight="1"

        android:text="이름"

        android:textSize="20dp"

        android:gravity="center"/>

    <TextView 

        android:id="@+id/txt_age"

        android:layout_width="0dp"

        android:layout_height="45dp"

        android:layout_weight="1"

        android:text="22"

        android:textSize="20dp"

        android:gravity="center"/>

    <TextView 

        android:id="@+id/txt_bool"

        android:layout_width="0dp"

        android:layout_height="45dp"

        android:layout_weight="1"

        android:text="true"

        android:textSize="20dp"

        android:gravity="center"/>

    

</LinearLayout>




- DataVo.java

package com.example.day0425;


public class DataVo {

private String img;

private String name;

private int age;

private String isBool;

public String getImg() {

return img;

}

public void setImg(String img) {

this.img = img;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public String getIsBool() {

return isBool;

}

public void setIsBool(String isBool) {

this.isBool = isBool;

}

}

 



- Manifest.xml

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

    package="com.example.day0425"

    android:versionCode="1"

    android:versionName="1.0" >


    <uses-sdk

        android:minSdkVersion="11"

        android:targetSdkVersion="21" />

    <uses-permission android:name="android.permission.INTERNET"/>

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>


    <application

        android:allowBackup="true"

        android:icon="@drawable/ic_launcher"

        android:label="@string/app_name"

        android:theme="@style/AppTheme" >

        

        <activity android:name="com.example.day0425.WebConnectActivity">

            <intent-filter>

                <action android:name="android.intent.action.MAIN" />


                <category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>

        </activity>

    </application>


</manifest>

 



- http://192.168.0.18:8080/index2.jsp

 {a:[{name:"토끼1",age:22,isBool:true},{name:"토끼2",age:25,isBool:true},{name:"토끼3",age:27,isBool:true}]}













반응형

댓글