Reputation: 405
This is similar to another problem I had earlier with textView which involved crashing of the app(which was solved), but now I am having a problem with editText because whenever I try to retrieve editText.getvalue(), even when it is outside the thread, it crashes the app.
Here is the code:
package awsomisoft.yemeb;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import awsomisoft.yemeb.R;
public class List extends Activity {
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
final TextView urlTextOut = (TextView) findViewById(R.id.URLtextView);
final EditText sear = (EditText) findViewById(R.id.editText);
new Thread() {
StringBuilder text = new StringBuilder();
@Override
public void run() {
try
{
String str = "";
URL url = new URL("http://mydomainname.com/"+sear.getText().toString()+"/test.meb");
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
while ((str = in.readLine()) != null) {
text.append(str);
}
in.close();
} catch (MalformedURLException e1)
{
} catch (IOException e)
{
}
runOnUiThread(new Runnable() {
@Override
public void run() {
urlTextOut.setText(text);
}
});
}
}.start();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.list, 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);
}
}
EDIT: Here is activity_list.xml -
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context="awsomisoft.yemeb.List"
android:id="@+id/List">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/URLtextView"
android:textSize="18dp" />
</RelativeLayout>
I tried to use Handlers before because there was a solution I found on here to use editText in threads, but it didn't solve the problem. I am assuming there is a solution to the problem, but I can't seem to find it. I just need a guide to see what I need to do with the editText in order to make sure the app doesn't crash. Thank you for any help. I apologize if there is an easy solution.
Upvotes: 0
Views: 1478
Reputation: 3767
If the EditText you're trying to access isn't in the layout that you're setting using
setContentView(R.layout.activity_list);
then it is going to set sear to a view that it can't find or (null):
final EditText sear = (EditText) findViewById(R.id.editText); // null
sear.getText().toString() // will now crash your app because
// you're trying to access a null object
In other words R.id.editText
needs to be in the layout activity_list.xml or you need to use the other xml file that it's already in when you setContentView(*.xml)
Upvotes: 0
Reputation: 5421
Normally you would allow an anonymous class to access outer class variables by declaring the variables final. However in your case since this is dealing with an edit text, you want this variable to be able to change, so final is not acceptable.
Your best bet in this situation is to make the thread a normal class rather than an anonymous class, and then pass the variable in a constructor (It needs to be a normal class because you can't have an explicitly declared constructor in an anonymous class).
public class MyThread implements Runnable {
StringBuilder text = new StringBuilder();
String editTextContents;
// Constructor
public MyThread(String editTextContents) { // <-- Pass in the string from EditText here
this.editTextContents = editTextContents;
}
@Override
public void run() {
try
{
String str = "";
URL url = new URL("http://mydomainname.com/"+ editTextContents +"/test.meb");
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
while ((str = in.readLine()) != null) {
text.append(str);
}
in.close();
} catch (MalformedURLException e1)
{
} catch (IOException e)
{
}
runOnUiThread(new Runnable() {
@Override
public void run() {
urlTextOut.setText(text);
}
}
}
}
You can invoke the thread in your activity with:
Runnable myRunnable = new MyThread(editTextContents);
new Thread(myRunnable).start;
Upvotes: 1