必须从UI线程(Android Studio)调用方法getText()

我正在尝试为应用程序创建登录。 但是我有一个问题。

这是我的代码:

package com.forgetmenot.loginregister; import java.util.ArrayList; import java.util.List; import org.apache.http.NameValuePair; import org.apache.http.message.BasicNameValuePair; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.app.Activity; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.EditText; public class MainActivity extends Activity { EditText uname, password; Button submit; // Creating JSON Parser object JSONParser jParser = new JSONParser(); private static final String TAG = "Login"; JSONObject json; private static String url_login = "http://localhost:8080/ForgetMeNotApplication/Login"; //JSONArray incoming_msg = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewsById(); submit.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { // execute method invokes doInBackground() where we open a Http URL connection using the given Servlet URL //and get output response from InputStream and return it. new Login().execute(); } }); } private void findViewsById() { uname = (EditText) findViewById(R.id.txtUser); password = (EditText) findViewById(R.id.txtPass); submit = (Button) findViewById(R.id.login); } private class Login extends AsyncTask{ @Override protected String doInBackground(String... args) { // Getting username and password from user input String username = uname.getText().toString(); String pass = password.getText().toString(); List params = new ArrayList(); params.add(new BasicNameValuePair("u",username)); params.add(new BasicNameValuePair("p",pass)); json = jParser.makeHttpRequest(url_login, "GET", params); String s=null; try { s= json.getString("info"); Log.d("Msg", json.getString("info")); if(s.equals("success")){ Intent login = new Intent(getApplicationContext(), home.class); login.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(login); finish(); } } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.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); } } 

Android studio说必须从istrctions的UI Thread调用方法getText()uname.getText().toString();password.getText().toString(); 可能的解决方案??

尝试通过execute(param1, param1, ..., paramN)方法将您的值传递给Login AsyncTask

 submit.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { String username = uname.getText().toString(); String pass = password.getText().toString(); new Login().execute(username, pass); } }); } private void findViewsById() { uname = (EditText) findViewById(R.id.txtUser); password = (EditText) findViewById(R.id.txtPass); submit = (Button) findViewById(R.id.login); } private class Login extends AsyncTask{ @Override protected String doInBackground(String... args) { // Getting username and password from user input String username = args[0]; String pass = args[1]; 

make usernamepass login类变量并覆盖onPreExcecute()并执行以下操作:

  @Override protected void onPreExecute() { username = uname.getText().toString(); pass = password.getText().toString(); } 

您正在从后台线程访问UI线程:

 String username = uname.getText().toString(); String pass = password.getText().toString(); 

您要做的只是将用户名/密码字符串传递给后台任务构造函数,或者您可以将它们直接传递给execute方法。 我更喜欢将它们定义到构造函数中(如果它们是必需的)(就像你的那样)。

定义你的LoginTask就好

 String uname; String password; public Login(String username, String password({ this.uname = username; this.password = password; } 

然后在doInBackground()中使用成员。

 List params = new ArrayList(); params.add(new BasicNameValuePair("u",this.username)); params.add(new BasicNameValuePair("p",this.pass)); json = jParser.makeHttpRequest(url_login, "GET", params); 

编辑 – 那么你的新Login()。execute()调用看起来会更像这样

 new Login(uname.getText().toString(), password.getText().toString()).execute(); 

除非事情发生了我不知道的事情,否则这应该不是问题。 UI元素无法从后台更新,但访问其getter从未成为问题。

无论如何,你可以通过在AsyncTask添加一个构造函数来解决这个问题,这个构造函数会接受两个String然后在创建任务时发送它们。

 private class Login extends AsyncTask{ // member variables of the task class String uName, pwd public Login(String userName, String password) { uName = userName; pwd = password; } @Override protected String doInBackground(String... args) {...} 

并在你的onClick()传递它们

  @Override public void onClick(View arg0) { // execute method invokes doInBackground() where we open a Http URL connection using the given Servlet URL //and get output response from InputStream and return it. // pass them here new Login(uname.getText().toString(), password.getText().toString()).execute(); } 

抛出exception是因为从后台线程调用了doInBackground() 。 我会将两个String参数添加到Login类的构造函数中。

我想建议您在Android上获得有关AsyncTasks和Threading的更多知识。 例如,官方文档中有一个页面: http : //developer.android.com/guide/components/processes-and-threads.html 。

您可能还会看一下这门课程: https : //www.udacity.com/course/developing-android-apps–ud853 。 您可以学习很多Android框架的基础知识。