how to get server data after fragment is created without freezing ui - android

I have two fragments and I have slide in, slide out transitions between fragments, after my fragment is loaded, I try to fetch data from server and load data into an array adapter, my problem is, I see my fragments freeze between transitions, I use execute to execute my asynctask in background, here is my code, DownloadJson extends to AsyncTask
public void onResume() {
DownloadJson downloadJson = new DownloadJson();
downloadJson.execute("http://somesite.com");
}
How can I start fetching data after fragment is loaded without freezing between transitions, thank you

Just use thread insted using asynctask.
asynctask still work in ui thread.
new Thread(new Runnable() {
#Override
public void run() {
//download jason... after that
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
//you can access to ui here when download is finished...
});
}
}).start();

At first, you can't use any network activity on main UI Thread, you'll get a NetworkException. You can solve this by using new Thread(new Runnable() {....}); , something like this :
DownloadJson downloadJson = new DownloadJson();
Thread t = new Thread()
{
#Override
public void run() {
try {
downloadJson.execute("http://somesite.com");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
//move on with the code, and get data from Thread.
t.start();
I'm casting into JSONObject for demo only, you need to set the right cast on your side.

Related

Threading Error

I get some error. I really couldn't solve it today :( I get error after set ID data to lblID in FillData() method. It sets ID data properly but lblTitle and lblPrice always returns error like "Only the original thread that created a view hierarchy can touch its views" and program stops running.
Note : This is not my original code. I just minimized it to be more understandable and of course it gives same error like below code. Anyway in FillData() method i get data from wcf service and it returns data properly. i tried runonuithread but it didn't make any sense. Also if i write the code outside of the thread it doesn't fill the controls. Because it's originally gets the data from wcf service.
public class MainActivity extends AppCompatActivity {
LinearLayout lytData;
TextView lblTitle, lblID, lblPrice;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lytData = (TextView)findViewById(R.id.lytNewData);
lblID = (TextView)findViewById(R.id.lblID);
lblTitle = (TextView)findViewById(R.id.lblTitle);
lblPrice = (TextView)findViewById(R.id.lblPrice);
new Thread() {
public void run() {
FillData();
}
}.start();
lytData.setOnTouchListener(new OnCustomTouchListener (context) {
#Override
public void ToLeft() {
new Thread() {
public void run() {
FillData();
}
}.start();
}
#Override
public void ToRight() {
new Thread() {
public void run() {
FillData();
}
}.start();
}
});
}
void FillData() {
lblID.setText("aaa");
lblTitle.setText("aaa");
lblPrice.setText("aaa");
}
The problem is you're trying to update the UI in another thread, but the UI can only be updated in the UI thread. If you're simply updated the UI as your code is showing then you should remove the calls from FillData from the secondary thread, use a secondary thread if you're doing heavy loading inside FillData() otherwise you're better off updating the UI directly in the UI thread:
So instead of doing this:
new Thread() {
public void run() {
FillData();
pd.cancel();
}
}.start();
Just simply call FillData(); outside the new thread.
You can also call runOnUiThread to bring the update to the ui thread:
getActivity().runOnUiThread(new Runnable() {
public void run() {
FillData();
}
});
If your code inside FillData is mixed with heavy load code, then you can bring the runOnUiThread method to inside the FillData and move only the UI update code to runOnUiThread.
If you still want to keep your code the way it is you can "post" changes from your secondary thread like this:
viewElement.post(new Runnable() {
public void run() {
//update UI
}
});
}
viewElement is any UI element that extends from View.

android: update UI from another thread in another class

The scenario is
I have two threads and a UI thread. The UI thread when clicked on login button creates a ClientThread which creates a socket and runs until the socket is connected, whenever a message is received i use a handler to post message to another thread called ProcessDataThread, now on receiving some messages from server i need to update UI related stuff from ProcessDataThread, I searched around alot and i found these two ways runonUiThread function which i guess can only be run from the Activity Class which is useless and the Asynctask method which i am not sure how to pass the activity context to...
Here is the code
The code executed when clicked on Login Button in the MainActivity
public void onLoginClick(View view)
{
global_constants.clientObject = new ClientThread();
global_constants.clientThread = new Thread(global_constants.clientObject);
global_constants.clientThread.start();
}
The code in ClientThread run method
public class ClientThread implements Runnable {
.......
#Override
public void run() {
......
while(!Thread.currentThread().isInterrupted() && (!CloseThread))
{
byte[] buff;
....
global_constants.updateConversationHandler.post(new ProcessDataThread(buff));
}
}
}
The method code in ProcessDataThread after parsing out the incoming data and stuff
public class ProcessDataThread implements Runnable {
.........
void ProcessLoginFailedPacket(byte[] buff)
{
// how to call the UI thread from here for updating some UI elements??
}
}
[EDIT]
i stored the activity context in a global variable and then did it this way, but i dont know whether it will be safer or not
((Activity)global_constants.MainContext).runOnUiThread(new Runnable(){
public void run()
{
TextView txtErr = (TextView) ((Activity)global_constants.MainContext).findViewById(R.id.errMsg);
txtErr.setVisibility(0);
txtErr.setText(reason);
}
});
You can post a runnable which does the UI operation to main thread as follows,
public class Utils {
public static void runOnUiThread(Runnable runnable){
final Handler UIHandler = new Handler(Looper.getMainLooper());
UIHandler .post(runnable);
}
}
Utils.runOnUiThread(new Runnable() {
#Override
public void run() {
// UI updation related code.
}
});

Android difference between Thread and AsyncTask

I've been trying to connect to a server to retrieve some data. First thing came to my mind was to create a thread to connect asynchronously.
new Thread(new Runnable() {
#Override
public void run() {
// retrieve data
}
}).run();
But the weird thing is that the thread I created worked synchronous with UI thread and I got a network exception so I ended up using AsyncTask. Do you guys know what could cause a thread to work non asynchronously with the UI thread? My class extends to a fragment.
Your must start your thread with start() and not run() in order to start the new thread:
new Thread(new Runnable() {
#Override
public void run() {
// retrieve data
}
}).start();

how to change UI element in a new thread task.onDone()?

How can I make this happend?
Thread t = new Thread(new Runnable() {
#Override
public void run() {
FacebookConnectTask task =
new FacebookConnectTask("facebookId", "token", "email", facebookGender,0, 0);
task.setOnPreExecuteListener(this);
task.setOnDoneListener(this);
task.execute();
}
});
t.start();
public void onPreExecute() {
progressbar.setVisibility(View.VISIBLE);
}
public void onDone() {
progressbar.setVisibility(View.GONE);
}
Since I am opening a new thread, I can not change a UI element in it, so, How can I manage to do something to the UI, when the task starts and when it's finished?
You could do the work in an AyncTask. The AsyncTask executes everything in doInBackground() inside of another thread, which does not have access to the GUI where your views are.
preExecute() and postExecute() offer you access to GUI before and after the heavy lifting occurs in this new thread, you can even pass the result of the long operation to postExecute() to then show any results of processing.
More here: http://developer.android.com/reference/android/os/AsyncTask.html
Example here: http://www.vogella.com/articles/AndroidPerformance/article.html
inside your activity
private Handler myHandler=new Handler();
next in your on done callback
public void onDone() {
myHandler.post(new Runnable(){
#Override
public void run() {
progressbar.setVisibility(View.GONE)
}
})
}
But as already was said. AsyncTask is more siutable for it

Android - How to create multiple threads to run at background?

I am new to Android, but I ran into this problem...
I need an infinite loop to run some process in the background,
while another infinite loop to accept some socket connection,
and then when a button clicked, I need to make a socket connection to some server.
Almost all the example and tutorial I can find are showing how to create one single thread.
I have try to use runnable (this seems to run at foreground?)
Runnable r=new Runnable() {
public void run() {
while(true){}
}
}; r.run();
and I have tried to use AsyncTask (this run at background, but only one AsyncTask per activity?)
private class Run extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... params) {
}
}
but whatever I do, my program only execute the first thread.
My question would be, is it possible to have multi-thread running multi-infinite loop within one activity? If is, how?
Yes, you can create multiple threads.
You can implement the Runnable interface.
new Thread(new Runnable() {
public void run() {
while (true) {
//code something u want to do & it will run infinitely.
//Remove the infinite loop for running finite set of operations.
Log.i("Thread", "Running parallely");
}
}
}).start();
Also, please note that the above thread run indefinitely. If you want to do any finite operations, just put the code inside the run method.
To create a thread that listen for network Connection
new Thread(new Runnable() {
public void run()
{
ServerSocket s = new ServerSocket(PORT_NUMBER);
while(true)
{
Socket c = s.accept();
// read the socket
BufferedReader in = new BufferedReader(new InputStreamReader(c.getInputStream()));
in.read();
}
c.close(); //close the socket
}
}).strat();
Sometimes you want to call up the UI thread from the background thread. You can do that like this:
Thread t = new Thread(new Runnable() {
public void run() {
//Do your background thing here
getActivity().runOnUiThread(new Runnable() {
public void run() {
//Update your GUI here
}
});
t.start();
And getActivity looks like this:
public class YourClass extends AppCompatActivity{
private Activity getActivity(){
return this;
}
//Rest of class here
}

Categories

Resources