【问题标题】:Android, how can i encapsulate an AsyncTask class with network connectionsAndroid,我如何用网络连接封装一个 AsyncTask 类
【发布时间】:2011-11-25 13:43:59
【问题描述】:

我从 android 开始(3 天前),我无法得到我想要的解决方案。所以,我在这里阅读了很多关于 asyncTask 的帖子,现在我确定我很困惑。

首先,这是我的第一个问题,所以我希望我至少做对了。

我想要的是有一个类来连接到某个服务器以及它的结果。然后分析json或xml。

所以这就是我所做的。 这是我的活动课(从主课调用)

    public class LogIn extends Activity implements OnClickListener {

    Button btn =null;

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

    btn = (Button) findViewById(R.id.btn_login);
    btn.setOnClickListener( this);
}   

public void onClick(View view) {
    HttpResponse response;
    Intent data = new Intent();
    //---get the EditText view---
    EditText txt_user = (EditText) findViewById(R.id.et_un);
    EditText txt_pwd =  (EditText) findViewById(R.id.et_pw);

    // aca tengo q llamar al conectar y chequear en BD
    ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();
    postParameters.add(new BasicNameValuePair("usr", txt_user.getText().toString()));
    postParameters.add(new BasicNameValuePair("pass", txt_pwd.getText().toString()));
    String URL="whatever";
    try {
        response= new ConectServer(URL, postParameters).execute().get();

        LeerAutentificacionXml l= new LeerAutentificacionXml(response);
        String s=l.Transformar();
        data.setData(Uri.parse(s.toString()));
        setResult(RESULT_OK, data);
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    //---set the data to pass back---
//  data.setData(Uri.parse(txt_user.getText().toString()+ " " + Uri.parse(txt_pwd.getText().toString())));
//  setResult(RESULT_OK, data);
    //---closes the activity---
    finish();
} }

这是我连接到网络服务的类。

    public class ConectServer extends AsyncTask <Void, Void, HttpResponse> {

private String URL=null;
private ArrayList<NameValuePair> postParameters=null;
/** Single instance of our HttpClient */
private HttpClient mHttpClient;
/** The time it takes for our client to timeout */
public static final int HTTP_TIMEOUT = 30 * 1000;


  public ConectServer(String url, ArrayList<NameValuePair> p) {
      this.URL=url;
      this.postParameters=p;
  }

 private HttpClient getHttpClient() {
     if (mHttpClient == null) {
         mHttpClient = new DefaultHttpClient();
         final HttpParams params = mHttpClient.getParams();
         HttpConnectionParams.setConnectionTimeout(params, HTTP_TIMEOUT);
         HttpConnectionParams.setSoTimeout(params, HTTP_TIMEOUT);
         ConnManagerParams.setTimeout(params, HTTP_TIMEOUT);
     }
     return mHttpClient;
 }

 /**
 * Performs an HTTP Post request to the specified url with the
 * specified parameters.
 *
 * @param url The web address to post the request to
 * @param postParameters The parameters to send via the request
 * @return The result of the request
 * @throws Exception
 */
@Override
protected HttpResponse doInBackground(Void... params) {
    // TODO Auto-generated method stub
     HttpResponse response = null;
     try {
         HttpClient client = getHttpClient();
         HttpPost request = new HttpPost(this.URL);
         UrlEncodedFormEntity formEntity;
         formEntity = new UrlEncodedFormEntity(this.postParameters);
         request.setEntity(formEntity);
         response = client.execute(request);
     } catch (UnsupportedEncodingException e) {
         e.printStackTrace();
     } catch (ClientProtocolException e) {
        e.printStackTrace();
     } catch (IOException e) {
        e.printStackTrace();
    }

    return response;
}


public void onPreExecute() {
     super.onPreExecute();

}

protected void onPostExecute(HttpResponse response) {
     super.onPostExecute(response);
}}

我读到了一些关于监听器的设计模式,但首先我想更好地理解为什么这不起作用。 我从服务器收到一个错误,我想知道这是否正确或发生了哪个重大的 newby 失败。

提前致谢。

【问题讨论】:

    标签: android android-asynctask encapsulation network-connection


    【解决方案1】:

    尝试将你的网络代码全部封装在异步任务中,这样你就可以这样调用它:

    EditText txt_user = (EditText) findViewById(R.id.et_un);
    EditText txt_pwd =  (EditText) findViewById(R.id.et_pw);
    new LoginTask(txt_user.getText(), txt_pwd.getText(), this).execute();
    

    根据您问题中的代码,LoginTask 类似于以下内容:

    public class LoginTask extends AsyncTask<Void, Void, String> {
    
        // The URL probably won't change, so keep it in a static field
        private final static String URL = "http://....";
    
        private final String username;
        private final String password;
        private final Activity activity;
    
        /*
         * Pass all data required to log in and handle the result here.
         */
        public LoginTask(final String username, final String password, final Activity activity) {
            this.username = username;
            this.password = password;
            this.activity = activity;
        }
    
        /*
         * Do all the network IO and time-consuming parsing in here,
         * this method will be invoked in its own thread, not blocking the UI.
         */
        @Override
        protected String doInBackground(Void... params) {
            HttpClient client = getHttpClient();
            try {
                HttpEntity formEntity = new UrlEncodedFormEntity(Arrays.asList(
                        new BasicNameValuePair("usr", username),
                        new BasicNameValuePair("pass", password)));
    
                HttpPost request = new HttpPost(URL);
                request.setEntity(formEntity);
    
                HttpResponse response = client.execute(request);
    
                LeerAutentificacionXml l= new LeerAutentificacionXml(response);
                return l.Transformar();
            } catch (IOException ex) {
                // properly log your exception, don't just printStackTrace()
                // as you can't pinpoint the location and it might be cut off
                Log.e("LOGIN", "failed to log in", ex);
            } finally {
                client.getConnectionManager().shutdown();
            }
        }
    
        private HttpClient getHttpClient() {
            return null; // insert your previous code here
        }
    
        /*
         * This again runs on the UI thread, so only do here
         * what really needs to run on the UI thread.
         */
        @Override
        protected void onPostExecute(String response) {
            Intent data = new Intent();
            data.setData(Uri.parse(response));
            activity.setResult(Activity.RESULT_OK, data);
        }
    }
    

    即使您不认为登录是一项“长时间运行的任务”,根据定义,任何涉及网络 IO 的任务都可能由于您无法控制的原因而挂起、超时等。

    拥有多个做网络IO的类并没有错,只要像上面LoginTask示例那样仔细封装细节即可。尝试编写两三个这种类型的AsyncTask 类,然后看看你是否可以将公共部分提取到一个公共的“网络内容”AsyncTask 中。不过,不要一次全部完成。

    【讨论】:

      【解决方案2】:

      调用asyncTask.get() 等待AsyncTask 完成,然后返回结果。它基本上违背了AsyncTask 的目的——AsyncTask 的全部意义在于长时间运行的任务在后台线程中执行,并且在此期间 UI 线程没有被阻塞。当您调用 .get() 时,它会阻止 UI 线程等待后台线程完成。

      所以,不要使用get() 并将结果可用时应该发生的所有操作移至onPostExecute(..)。像这样的:

      protected void onPostExecute(HttpResponse response) {
          super.onPostExecute(response);
          LeerAutentificacionXml l= new LeerAutentificacionXml(response);
          String s=l.Transformar();
          data.setData(Uri.parse(s.toString()));
      }
      

      当然,您必须将一些引用 (data?) 传递给 AsyncTask(通过构造函数或其他方式)。

      【讨论】:

      • 我明白,但我只想要一个类连接到服务器,在这种情况下,登录不是一项长时间运行的任务,但我必须获取一些图片,例如当用户阅读一些图片时文本,这应该是最好的选择吧?你推荐什么?每个班级管理他们与服务器的连接?
      • 你有多个活动吗?
      猜你喜欢
      • 2015-03-21
      • 2012-11-20
      • 1970-01-01
      • 2019-01-15
      • 2012-11-20
      • 2013-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多