I'm trying to send a variable string to Runnable, but find myself having to create two variables for this. One normal string content and one final string finalcontent that is assigned the content of the other string.
String content = "";
try {
content = response.body().string();
} catch (IOException e) {
// Handle exception
}
final String finalcontent = content;
runOnUiThread(new Runnable() {
#Override
public void run() {
TextView text = (TextView)findViewById(R.id.textView);
text.setText(finalcontent);
}
});
Is this the normal way to do this or is there a better way to avoid creating two variables?
it's limitation of Java language design but you should be able to write
final String content;
try {
content = response.body().string();
} catch (IOException e) {
content = "";
// Handle exception
}
runOnUiThread(new Runnable() {
#Override
public void run() {
TextView text = (TextView)findViewById(R.id.textView);
text.setText(content);
}
});
You may create a custom implementation of Runnable, here is an example
void foo(){
String content = "";
try {
content = response.body().string();
} catch (IOException e) {
// Handle exception
}
runOnUiThread(new MyCustomRunnable(content));
}
private class MyCustomRunnable implements Runnable {
private String content;
public MyCustomRunnable(String content) {
this.content = content;
}
#Override
public void run() {
TextView text = (TextView)findViewById(R.id.textView);
if (text != null) {
text.setText(content);
}
}
}
Why don't use RxJava?I think you just want to update UI after you get data from internet.
Observable observable = Observable.create(OnSubscribe()...)
.subscribeOn(Shceduler.io).observeOn(AndroidSchedulers.mainthread)
Related
Parse HTML with jsoup and string builder add white space in the final result.
First, it shows title and then strings from tag between the string title and tag p there is white space. thankyou
MainActivity
TextView tvidescription;
#Override
protected void onCreate ( Bundle savedInstanceState ) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
new Thread(new Runnable() {
#Override
public void run () {
final StringBuilder builder = new StringBuilder();
try {
Document doc = Jsoup.connect("https://jang.com.pk/news/497717").get();
Elements links = doc.select("p");
String title = doc.title();
builder.append(title);
for (Element link : links) {
builder.append("\n").append("\n").append(link.text());
}
} catch (IOException e) {
builder.append("Error : ").append(e.getMessage()).append("\n");
}
runOnUiThread(new Runnable() {
#Override
public void run () {
tvidescription.setText(builder);
}
});
}
}).start();
return null;
}
}
Try
doc.outputSettings().prettyPrint(false);
this will remove white spaces.
I have two classes, one is Activity, and one is Thread class:
Activity:
public class MainActivity extends AppCompatActivity {
ObjectInputStream inFromServer = null;
ObjectOutputStream outToServer=null;
Socket clientSocket = null;
String userName;
EditText message;
static TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
message = (EditText)findViewById(R.id.txtMessage);
textView = (TextView)findViewById(R.id.textView);
try {
clientSocket = new Socket("10.0.0.41", 10002);
outToServer =
new ObjectOutputStream(clientSocket.getOutputStream());
inFromServer =
new ObjectInputStream((clientSocket.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
ReceiveMessages receiveMessages = new ReceiveMessages(inFromServer);
receiveMessages.start();
}
public void onClickSend(View view) throws IOException {
outToServer.writeObject("Eliran!" + message.getText().toString());
}
public void btnUserName(View view) throws IOException {
EditText editText = (EditText)findViewById(R.id.userName);
userName = editText.getText().toString();
outToServer.writeObject(userName + "!");
}
}
Thread class:
public class ReceiveMessages extends Thread {
ObjectInputStream inFromServer = null;
public ReceiveMessages(ObjectInputStream inFromServer)
{
this.inFromServer = inFromServer;
}
public void run() {
try {
while (true) {
String message = (String) inFromServer.readObject();
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
I want to set text in the text view of the activity in the Thread class.
How can I do it? InflateLayout isn't helping I think.
I would go about it by creating a Callback that gets called when the String is received from the aerver.
interface ReceiveMessageListener {
void onMessageReceived (String message);
}
Then have my Activity implement the interface and set the text in the onMessageReceived call back.
#Override
public void onMessageReceived (String message) {
runOnUiThread(new Runnable() {
#Override
public void run () {
textView.setText(message);
}
});
}
You'll also have to change the constructor for your MessageReceive class to take a MessageReceiveListener.
From your Activity:
ReceiveMessages receive = new ReceiveMessages(input, this);
Only the UI thread can interact with ui elements (such textview). Try using runOnOiThread or mainHandler.post ()
I have list of web pages(over 100) with I have to vistit and collect data from.
I decided to save the html from all of them to one file, and then use Jsoup to find the interesting data.
But problem is to I do not know how to run 100 threads, and save the responses into one file, any ideas?
maybe it's not a masterpiece, but it works, and I wanted to make it as simple as possible.
ArrayList<String> links = new ArrayList<>();
Elements myDiv;
private void saveDetails() throws IOException {
if(repeat < links.size()){
repeat++;
textView.setText(String.valueOf(repeat));
saveFile(myDiv.toString());
myDiv = null;
getDetails(links.get(repeat));
}else {
textView.setText("finished");
}
}
private void getDetails(String urlStr) {
final String detailsUrl = urlStr;
new Thread() {
#Override
public void run() {
Message msg = Message.obtain();
try {
Document doc = Jsoup.connect(detailsUrl).get();
myDiv = doc.select(".exhibitor-contact");
} catch (IOException e1) {
e1.printStackTrace();
}
detailsHandler.sendMessage(msg);
}
}.start();
}
private Handler detailsHandler = new Handler() {
public void handleMessage(Message msg) {
super.handleMessage(msg);
try {
saveDetails();
} catch (IOException e) {
e.printStackTrace();
}
}
};
You don't need to save all of them in a file and then process them. You can gather information one by one. It is my suggestion:
arrayList urls = {100 site-url}; //in correct syntax
Document doc = null;
for (String url : urls) {
doc = Jsoup.connect(url).get();
//now proccess doc.toString as you want(in regular expression for example)
//save your desired information
}
I am fetching title, date and image from an online xml file and storing it in a arraylist. I have taken 3 different arraylists for storing title , date and image.
I am successful in getting image urls , my problem is how to download image from the url and show it in a imageview. The code for fetching the url is below.
if((xpp_name.equals("content")))
{
xpp.next();
strvalue=xpp.getText();
if(strvalue!=null){
String url = strvalue.substring(
strvalue.indexOf("src")+5,, strvalue.indexOf("jpg")+3);
arrayList_for_images.add(url);
}
xpp.next();
xpp.next();}
Start a new thread for downloading image from Url and set image in imageview in handler.
private Bitmap pop_up_image_bitmap ;
private Handler handler ;
private Runnable r;
new Thread(new Runnable() {
#Override
public void run() {
URL newurl;
try {
newurl = new URL(<Url>);
pop_up_image_bitmap = BitmapFactory.decodeStream(newurl.openConnection() .getInputStream());
handler.post(r);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
Put handler :
handler = new Handler();
r = new Runnable()
{
public void run()
{
if(pop_up_image_bitmap!=null){
imageview.setImageBitmap(pop_up_image_bitmap);
handler.postDelayed(this, 1000);
popUpImageProgressBar.setVisibility(View.INVISIBLE);
}
}
};
handler.postDelayed(r, 1000);
Here you can find a lazy loading library to download images from a URL and show them in a ListView. Also i suggest you to avoid using 3 different Arraylists and use only one ArrayList, instead, with a custom class that is used to store the information of an image(title, date and image url).
EDIT: Here is an example class that holds the information needed for the image:
import java.util.Date;
public class ImageObject {
private String image_name;
private String image_url;
private Date image_date;
public ImageObject() {
}
public ImageObject(String image_name, String image_url, Date image_date) {
this.image_name = image_name;
this.image_url = image_url;
this.image_date = image_date;
}
public void setImageName(String image_name) {
this.image_name = image_name;
}
public void setImageURL(String image_url) {
this.image_url = image_url;
}
public void setImageDate(Date image_date) {
this.image_date = image_date;
}
public String getImageName() {
return this.image_name;
}
public String getImageURL() {
return this.image_url;
}
public Date getImageDate() {
return this.image_date;
}
}
Here is an example usage in witch i initiate a ArrayList with one ImageObject:
ArrayList<ImageObject> data = new ArrayList<ImageObject>();
ImageObject obj = new ImageObject("test.jpg", "www.imageurl.com", new Date());
data.add(obj);
And this is how you retrieve a value from a certain ImageObject object from the ArrayList:
data.get(0).getImageName();
try out this best image loading library ever.
https://github.com/nostra13/Android-Universal-Image-Loader
Hi and thank you for looking at my question.
I am an intermediate programmer in C but an Android newbie. I have been trying to get a chat programming working. Assuming everything else in the code below works perfectly. The one question I like to ask is when I try to setText() from a thread running, I get an exception above. I looked at many many websites and here too. Found many things, but I really do not understand. Please explain to me in the most simple way or offer me some simple fix if possible.
Thank you very much!!
public class chatter extends Activity {
private String name = "Unknown User";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final EditText msgToServer = (EditText) findViewById(R.id.msgBox);
final EditText chatFromServer = (EditText) findViewById(R.id.chatBox);
final Button MsgToServer = (Button) findViewById(R.id.sendButton);
Socket socket = null;
String ipAddress = "192.168.1.103";
try {
InetAddress serverAddr = InetAddress.getByName(ipAddress);
Socket socketMain = new Socket(serverAddr, 4444);
socket = socketMain;
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e("TCP", "error", e);
}
final OutMsg outMsg = new OutMsg(socket);
Thread msgSenderThread = new Thread(outMsg);
msgSenderThread.start();
//chatFromServer.post(new InMsg(socket, chatFromServer));
Thread msgReceiverThread = new Thread(new InMsg(socket, chatFromServer));
msgReceiverThread.start();
MsgToServer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String msgToServerString;
msgToServerString = msgToServer.getText().toString();
outMsg.message = name + ": " + msgToServerString;
outMsg.readyToSend = true;
msgToServer.setText("");
}
});
}
public void updateResultsInUi (String msg)
{
final EditText chatFromServer = (EditText) findViewById(R.id.chatBox);
chatFromServer.setText(msg);
}
public class InMsg implements Runnable {
Socket socket;
EditText chatFromServer;
public InMsg(Socket socket, EditText chatFromServer)
{
this.socket = socket;
this.chatFromServer = chatFromServer;
}
public void run(){
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String str = "FIRSTMESSAGEFROMSERVER";
while (true)
{
if (str.equals("FIRSTMESSAGEFROMSERVER"))
str = in.readLine();
else
str = str + "\n" + in.readLine();
Log.e("TCP", "got the message: " + str);
//Here is where went wrong******************
chatFromServer.setText(str);
//******************************************
}
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e("TCP", "error in receiving", e);
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.setNameMenu:
setname();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void populateChatBox (String msgFromS)
{
Log.e("TCP", "going in to popC");
final EditText textNameInput = (EditText) findViewById(R.id.nameBox);
Log.e("TCP", " popC");
textNameInput.setText(msgFromS);
Log.e("TCP", "going out from popC");
}
public void setname()
{
setContentView(R.layout.custom_dialog);
final EditText textNameInput = (EditText) findViewById(R.id.nameBox);
Button submitNameButton = (Button) findViewById(R.id.submitNameButton);
submitNameButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
String nameinput = textNameInput.getText().toString();
if (!name.equals(""))
name = nameinput;
setContentView(R.layout.main);
}
});
}
}
In your run() method:
Message msg = new Message();
String textTochange = "text";
msg.obj = textTochange;
mHandler.sendMessage(msg);
Create the mHandler in your UI thread;
Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
String text = (String)msg.obj;
//call setText here
}
};
You are not on the UI thread when setting the text. You need to be on UI if you want to work on UI items. Create a message handler on the UI thread, post your messages to it and call setText from the handler on the UI thread.
you can do this whenever you are in a thread:
msgToServer.post(new Runnable() {
public void run() {
msgToServer.setText("your text here");
}
}
Your problem is that there are certain interactions that you can only do on the UI thread. This is one of them.
Looks like you might want to use AsyncTask
http://developer.android.com/reference/android/os/AsyncTask.html
Basically you could make your Runnable an AsyncTask instead and do the setText in onProgressUpdate, which gets run on the UIThread.
If you would like to use an AsyncTask to run in the background this is how I would do it:
public class UpdateTextProgress_Task extends AsyncTask<Void,String,Void> {
Socket socket;
EditText chatFromServer;
UpdateTextProgress_Task(EditText chatFromServer, Socket socket){
this.socket = socket;
this.chatFromServer = chatFromServer;
}
#Override
protected Void doInBackground(Void... params) {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String str = "FIRSTMESSAGEFROMSERVER";
while(true){
if (str.equals("FIRSTMESSAGEFROMSERVER")){
str = in.readLine();
}
else{
str = str + "\n" + in.readLine();
}
Log.e("TCP", "got the message: " + str);
publishProgress(str); // calls the onProgressUpdate method
}catch (IOException e) {
Log.e("UpdateTextProgress", e.getMessage());
}
return null;
}
#Override
protected void onProgressUpdate(String... progress) {
chatFromServer.setText(progress[0]); //now we are on the UI thread so we can update our EditText
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
Log.e("UpdateTextProgress", "Finished");
}
}
To execute the code:
UpdateTextProgress_Task task = new UpdateTextProgress_Task(chatFromServer,socket);
task.execute();