2014-11-26 5 views
-1

Этот вопрос воспроизводится с this question, приведенный код является минималистическим примером проблемы. В этом примере мы потребляя temperature conversion SOAP web service of w3schools, используя ksoap2 библиотеку:Android AsyncTask как НЕ внутренний класс: Weird NullPointerException

Проблема заключается в том, что я получаю NullPointerException на ed = (EditText) mainActivity.findViewById(R.id.mainActivity_editText1); в MyTask. Я знаю, что я могу реализовать AsyncTask как внутренний класс, но я читал, что он может быть реализован как отдельный класс, поэтому почему эта проблема.

Это приложение имеет основную деятельность под названием MainActivity. У MainActivity есть метод onclick-listener, внутри которого запускается другое действие по имени SecondActivity.

MainActivity.java:

public class MainActivity extends Activity { 

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

    public void StartSecondActivity(View v) { 
     Intent intent = new Intent(this, SecondActivity.class); 
     startActivity(intent); 
    } 
} 

Тогда есть отдельный AsyncTask класс называется MyTask. Мы предоставляем конструктор MyTask для назначения активности (экземпляр MainActivity здесь), переданный ему, к объекту активности, который мы создаем внутри MyTask, который называется mainActivity, причиной которого является вызов метода Деятельности findViewById.

С SecondActivity мы создаем объект MyTask с использованием этого конструктора и передаем ему экземпляр основной деятельности в нашем приложении; а затем вызовите выполнение на этом объекте MyTask.

SecondActivity.java:

public class SecondActivity extends Activity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_second); 

     new MyTask(new MainActivity()).execute(); 
    } 
} 

Сейчас внутри MyTask, я читал EditText от основной деятельности. Затем используйте его как значение целина и добавьте его в запрос SOAP для вызова веб-службы. Затем в конце я показываю результат веб-службы в TextView в SecondActivity в onPostExecute.

MyTask.java:

public class MyTask extends AsyncTask<Void, Void, String> { 
    Activity mainActivity; 
    EditText ed; 
    TextView tv; 
    String searchString; 

    private static final String TAG = MyTask.class.getSimpleName(); 

    public static final String SOAP_ACTION = "http://www.w3schools.com/webservices/CelsiusToFahrenheit"; 
    public static final String METHOD_NAME ="CelsiusToFahrenheit"; 
    public static final String URL = "http://www.w3schools.com/webservices/tempconvert.asmx"; 
    public static final String NAMESPACE = "http://www.w3schools.com/webservices/"; 

    MyTask(Activity activity) { 
     mainActivity = activity; 
    } 

    @Override 
    protected void onPreExecute() { 
     if (mainActivity!=null) { 
      ed = (EditText) mainActivity.findViewById(R.id.mainActivity_editText1); 
     } else { 
      Log.i(TAG, "mainActivity is null."); 
     } 
     searchString = ed.getText().toString(); 
    } 

    @Override 
    protected String doInBackground(Void... params) { 
     SoapObject requestSoapObject = new SoapObject(NAMESPACE, METHOD_NAME); 
     requestSoapObject.addProperty("Celsius", searchString); 

     SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); 
     envelope.dotNet = true; 
     envelope.setOutputSoapObject(requestSoapObject); 

     HttpTransportSE htse = new HttpTransportSE(URL); 
     SoapPrimitive webServiceResultSoapPrimitive = null; 
     try { 
      htse.call(SOAP_ACTION, envelope); 
      webServiceResultSoapPrimitive = (SoapPrimitive) envelope.getResponse(); 

     } catch (HttpResponseException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (XmlPullParserException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     return webServiceResultSoapPrimitive.toString(); 
    } 

    @Override 
    protected void onPostExecute (String webServiceResultString) { 
     System.out.println("Sysout : " + webServiceResultString); 
     tv = (TextView) mainActivity.findViewById(R.id.secondActivity_textView1); 
     tv.setText("Fahrenheit : " + webServiceResultString); 
    } 

} 
+1

'новый MainActivity()'? Это не так, как это работает. –

+0

@PedroOliveira? Разве мы не создаем объект такого класса? Можете ли вы сказать мне правильный путь? – Solace

+0

Именно поэтому вы даете нисходящее движение? Потому что я делаю это неправильно? – Solace

ответ

2

Pedro Как говорится в his comment вы не хотите, чтобы попытаться создать экземпляр Activity путь вы.

Все что вам нужно сделать, это передать значение от первого до второго Activity. Затем вы можете передать это значение конструктору своего AsyncTask.

Итак, в вашем onClick() первых Activity вы передаете его как Extra.

public void StartSecondActivity(View v) { 
    Intent intent = new Intent(this, SecondActivity.class); 
    EditText et = (EditText) findViewById(R.id.mainActivity_editText1); 
    String temp = et.getText().toString(); 
    intent.putExtra("temp", temp); 
    startActivity(intent); 
} 

затем получить его и передать его к задаче

public class SecondActivity extends Activity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     // get the String 
     Intent i = getIntent(); 
     String temp = i.getStringExtra("temp"); 
     setContentView(R.layout.activity_second); 

     // and pass it here 
     new MyTask(temp).execute(); 
    } 
} 

теперь получить его в задаче

MyTask(String value) { 
    searchString= value; 
} 
+0

Для этой части, спасибо вам большое. Я, конечно, должен был это сделать. Теперь, все еще я вызываю 'findViewById' в' onPostexecute', что мне там делать? – Solace

+0

Что ты делаешь? Вызов второго действия только для запуска задачи, а затем передать значение обратно в первую активность? Я не вижу смысла во втором действии – codeMagic

+0

Нет, TextView, где я показываю результат, находится во втором действии. Хорошо, пытаясь вызвать 'findViewByActivity', чтобы найти представление о втором действии *, используя объект первого действия *, теперь является явной ошибкой, но все же мне нужно отобразить результат во втором действии. – Solace