当点击登陆之后,怎么把server端返回的数据,写到指定的控件上尼?,在android怎么实现尼?以下我们通过详细的代码进行分析和实现,希望能对你,在学习android知识上有所帮助。
以下通过代码说明:
package www.csdn.net.lesson03;
import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import android.app.Activity; import android.os.Bundle; import android.text.TextUtils; import android.view.View; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; public class LoginActivity extends Activity { // 声明控件对象private EditText et_name, et_pass;// 声明显示返回数据库的控件对象private TextView tv_result;@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);// 设置显示的视图setContentView(R.layout.activity_login);// 通过 findViewById(id)方法获取username的控件对象et_name = (EditText) findViewById(R.id.et_name);// 通过 findViewById(id)方法获取用户password的控件对象et_pass = (EditText) findViewById(R.id.et_pass);// 通过 findViewById(id)方法获取显示返回数据的控件对象tv_result = (TextView) findViewById(R.id.tv_result);}/*** 通过android:onClick="login"指定的方法 , 要求这种方法中接受你点击控件对象的參数v* * @param v*/public void login(View v) { // 获取点击控件的idint id = v.getId();// 依据id进行推断进行怎么样的处理switch (id) { // 登陆事件的处理case R.id.btn_login:// 获取usernamefinal String userName = et_name.getText().toString();// 获取用户passwordfinal String userPass = et_pass.getText().toString();if (TextUtils.isEmpty(userName) || TextUtils.isEmpty(userPass)) { Toast.makeText(this, "username或者password不能为空", Toast.LENGTH_LONG).show();} else { System.out.println("----------------------发送请求到server----------------------");// 訪问网络 (须要一个网络的权限) <uses-permission// android:name="android.permission.INTERNET"/>// 訪问网络(耗时的操作) 避免堵塞主线程(UI) 须要开启新的子线程来处理new Thread() { public void run() { // 调用loginByGet方法loginByGet(userName, userPass);};}.start();}break;default:break;}}/*** 通过GET方式发送的请求* * @param userName* @param userPass*/public void loginByGet(String userName, String userPass) { try { // 设置请求的地址 通过URLEncoder.encode(String s, String enc)// 使用指定的编码机制将字符串转换为 application/x-www-form-urlencoded 格式String spec = "http://172.16.237.200:8080/video/login.do?username="+ URLEncoder.encode(userName, "UTF-8") + "&userpass="+ URLEncoder.encode(userPass, "UTF-8");// 依据地址创建URL对象(网络訪问的url)URL url = new URL(spec);// url.openConnection()打开网络链接HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();urlConnection.setRequestMethod("GET");// 设置请求的方式urlConnection.setReadTimeout(5000);// 设置超时的时间urlConnection.setConnectTimeout(5000);// 设置链接超时的时间// 设置请求的头urlConnection.setRequestProperty("User-Agent","Mozilla/5.0 (Windows NT 6.3; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0");// 获取响应的状态码 404 200 505 302if (urlConnection.getResponseCode() == 200) { // 获取响应的输入流对象InputStream is = urlConnection.getInputStream();// 创建字节输出流对象ByteArrayOutputStream os = new ByteArrayOutputStream();// 定义读取的长度int len = 0;// 定义缓冲区byte buffer[] = new byte[1024];// 依照缓冲区的大小,循环读取while ((len = is.read(buffer)) != -1) { // 依据读取的长度写入到os对象中os.write(buffer, 0, len);}// 释放资源is.close();os.close();// 返回字符串String result = new String(os.toByteArray());System.out.println("***************" + result+ "******************");// 在这里把返回的数据写在控件上 会出现什么情况尼tv_result.setText(result);} else { System.out.println("------------------链接失败-----------------");}} catch (Exception e) { e.printStackTrace();}} }通过加入红色的代码进行实现,会发现出现例如以下bug:
05-24 06:38:37.987: W/System.err(1170): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.05-24 06:38:37.997: W/System.err(1170): at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6094)05-24 06:38:37.997: W/System.err(1170): at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:824)05-24 06:38:38.007: W/System.err(1170): at android.view.View.requestLayout(View.java:16431)05-24 06:38:38.007: W/System.err(1170): at android.view.View.requestLayout(View.java:16431)05-24 06:38:38.007: W/System.err(1170): at android.view.View.requestLayout(View.java:16431)05-24 06:38:38.007: W/System.err(1170): at android.view.View.requestLayout(View.java:16431)05-24 06:38:38.007: W/System.err(1170): at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:352)05-24 06:38:38.007: W/System.err(1170): at android.view.View.requestLayout(View.java:16431)05-24 06:38:38.007: W/System.err(1170): at android.widget.TextView.checkForRelayout(TextView.java:6600)05-24 06:38:38.007: W/System.err(1170): at android.widget.TextView.setText(TextView.java:3813)05-24 06:38:38.007: W/System.err(1170): at android.widget.TextView.setText(TextView.java:3671)05-24 06:38:38.017: W/System.err(1170): at android.widget.TextView.setText(TextView.java:3646)05-24 06:38:38.017: W/System.err(1170): at www.csdn.net.lesson03.LoginActivity.loginByGet(LoginActivity.java:134)05-24 06:38:38.027: W/System.err(1170): at www.csdn.net.lesson03.LoginActivity$1.run(LoginActivity.java:67)错误的原因是:
仅仅有原来的线程创建的视图层次能够触摸它的控件. 所以仅仅有在主线程中,才可以设置返回数据控件的内容。
那么怎么实现效果,我们能够使用Activity中给我们提供的runOnUiThread(action);的方法实现,把我们要进行设置返回数据控件的内容放在此方法中就可以。详细的部分代码例如以下:
// 返回字符串 final String result = new String(os.toByteArray()); System.out.println("***************" + result + "******************"); LoginActivity.this.runOnUiThread(new Runnable() { //才用此方法进行改动主线程中的UI控件内容 @Override public void run() { // 在这里把返回的数据写在控件上 会出现什么情况尼 tv_result.setText(result); } });測试效果例如以下:
以上代码仅供參考学习,如有问题请留言