How to use progresbar with handler to update main UI in android? - android

I need to display ProgressBar on button action and also need to update same activity page after successful action. ProgressBar is getting displayed but it hangs (it interrupts and hangs) on action process. Circle bar does not animate.
Code sample : ProgessBar is added in layout xml
<ProgressBar
android:id="#+id/loginProgressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:visibility="invisible"
android:layout_marginTop="100dp" />
Code behind : on button action
public void onClick(View view)
{
if(loginProgressBar ==null)
{
loginProgressBar = (ProgressBar)findViewById(R.id.loginProgressBar);
}
loginProgressBar.setVisibility(View.VISIBLE);
myHandler.post(new Runnable()
{
public void run()
{
Intent intent = new Intent(LoginActivity.this,RegisterActivity.class);
startActivity(intent);
}
});
}
It seems that myHandler is updating main UI and at the same time. ProgressBar is also part of Main UI, so it hangs.
Please provide solution so that ProgressBar works without any interruption.

What you need is an AsyncTask.
Take a look at the example in the link provided, it is exactly what you are looking for !
Hope it helps !

Related

setAnchorView not working with Recycler view

I am trying to build a music player.
I did everything what is required and the working is smooth but however i can't seem to see my MediaController Controls.
Declaration:private MusicController musicController;
public class MusicController extends MediaController {
public MusicController(Context context) {
super(context);
}
#Override
public void hide() {
}
}
MainActivity.java
musicController.setMediaPlayer(this);
musicController.setAnchorView(findViewById(R.id.my_recycler_view));
musicController.setEnabled(true);
mainactivity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:background="#FF330000"
android:layout_height="match_parent"
android:id="#+id/recycler_parent_view"
>
<android.support.v7.widget.RecyclerView
android:id="#+id/my_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
I have added a screenshot.
What could be the problem here?
MainActivity.java
MusicService.java
MusicController.java
MyAdaptor.java
I have included every file that might be important. Please help me look out the problem. Thank You.
I see musicController.show(0); being called only after some click events.
Should you call it also soon after having set the anchorView?
From documentation
void show (int timeout)
Show the controller on screen. It will go away automatically after 'timeout' milliseconds of inactivity.
Try just musicController.show();
EDIT
I saw you overrode the MusicController.hide() method so it shouldn't be removed after the timeout period, but still it seems to me you don't show it when you set the anchorView
UPDATE
musicController.setMediaPlayer(this);
musicController.setAnchorView(findViewById(R.id.my_recycler_view));
musicController.setEnabled(true);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
musicController.show();
}
}, 5000);
I ran your code and I was able to show the controller after applying a delay. Maybe you should show it after your service is connected...not sure about this, but at least you could try this code and then improve it.

Is a refresh icon in an Android Toolbar considered deprecated now (did 'swipe to refresh' totally take its place)?

My question is more from the design point of view, related to the Material design philosophy.
So do all newest apps now completely rely on the swipe to refresh UX pattern when it's possible to apply it (e.g. map activities cannot have it because they take over the swipe gesture)? Is it considered too "old-school" to put a refresh icon in the Toolbar (in the way that this ActionBar in the picture has it)?
Because my app shows realtime statistics to the user and I would like to be sure that 90% of the users will instantly know how to refresh them.
You can replace it with SwipeRefreshLayout.
add this to your xml file:
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/refreshLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ListView
android:id="#+id/mList"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.SwipeRefreshLayout>
and to you java file this:
SwipeRefreshLayout mRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.refreshLayout);
handler.postDelayed(refreshing, 100);
mRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
// YOUR TASK HERE.
}
});
EDIT:
To make user know that there's an refresh in your app you can use this to make it refresh automatically everytime app opens:
private Handler handler = new Handler();
private final Runnable refreshing = new Runnable() {
public void run() {
mRefreshLayout.setRefreshing(true);
try {
if (mRefreshLayout.isRefreshing()) {
// YOUR TASK HERE.
handler.removeCallbacks(this);
} else {
mRefreshLayout.setRefreshing(false);
}
} catch (Exception e) {
Log.e("", e.getMessage(), e);
}
}
};
in your task in onPreExecute() add this:
if (!mRefreshLayout.isRefreshing()) {
mRefreshLayout.setRefreshing(true);
}
and in onPostExecute() add this:
mRefreshLayout.setRefreshing(false);
Don't forget handler.postDelayed(refreshing, 100); after defining the SwipeRefreshLayout view.
https://www.google.de/design/spec/patterns/swipe-to-refresh.html
Alternatively, the manual refresh method requires users to initiate content updates via an action or gesture.
Note: an action or gesture.
The material design guide does not prohibit the button, it simply does not give such an emphasis to it. But if it's an important action for your app, you should certainly use it.
https://www.google.com/design/icons/#ic_refresh

Visibility of ProgressBar

I need to process some data when the user click the button in one activity, so the screen looks like the app stops for 2-3 seconds. It isn't a lot but I want to give the user information that everything is ok and IMO the best way will be the progressbar which is visible only when data are processed.
I found the code of ProgressBar and it looks like this:
<ProgressBar
android:id="#+id/loadingdata_progress"
style="?android:attr/progressBarStyle"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignBottom="#+id/fin2_note"
android:layout_centerHorizontal="true"
android:indeterminate="true"
android:visibility="invisible" />
and inserted it on the middle of my layout.
And to try if the progressbar works, I put this code
loadingimage= (ProgressBar) findViewById(R.id.loadingdata_progress);
loadingimage.setVisibility(View.VISIBLE);
into onCreate method and everything looks fine.
Then I recreated the code to show this progressbar only if the data is processed.
After click the user invoke this method
public void fin2_clickOnFinalization(View v)
{
loadingimage= (ProgressBar) findViewById(R.id.loadingdata_progress);
loadingimage.setVisibility(View.VISIBLE);
// code where data is processing
loadingimage.setVisibility(View.INVISIBLE);
}
and nothing appear on the screen. I don't know where is the mistake. If I found the progress bar by id, It's strange for me that I can control it in onCreate method but in onclick method it's out of my control.
Your UI thread cannot show progress bar cause it is busy due to your data processing. Try to use this kind of code :
public void fin2_clickOnFinalization(View v) {
new YourAsyncTask().execute();
}
private class YourAsyncTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... args) {
// code where data is processing
return null;
}
#Override
protected void onPostExecute(Void result) {
loadingimage.setVisibility(View.INVISIBLE);
super.onPostExecute(result);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
loadingimage.setVisibility(View.VISIBLE);
}
}
EDIT:
AsyncTask let you run code in separate thread and make app more responsive, just put time-consuming code inside doInBackground.
You're not giving the UI time to refresh. Your "data processing" code is running on the UI thread, blocking any visible changes. By the time the system gets control to refresh the display, you've already set it back to invisible.
To fix this, move your processing code to a separate thread or AsyncTask. Then you can set the progress bar to visible, start the task, and have it turn itself invisible once it's done.
I'd recommend AsyncTask for this purpose about 90% of the time on Android, since it comes stock with useful callbacks. The developer guide for it(in the Javadoc linked above) is pretty explicit, and outlines all the steps you need to take.
AsyncTask is too heavily-weighted for such task.
A better much solution
Handler handler = new Handler(getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
loadingimage.setVisibility(View.VISIBLE);
}
});
Or even simpler (does essentially the same thing as solution above)
runOnUiThread(new Runnable() {
#Override
public void run() {
loadingimage.setVisibility(View.VISIBLE);
}
});
You can try to create a global ProgressDialog not in the layout but in your activity like:
public class MyActivity {
ProgressDialog progress = null;
protected void onCreate(...) {
progressDialog = new ProgressDialog(this);
progressDialog.setCancelable(false);
progressDialog.setTitle("Progress");
}
public void fin2_clickOnFinalization(View v)
{
progress.show();
// code where data is processing
progress.dismiss();
}
}
Hope i it helps

How can I use the circular Progress bar between two activities properly?

I have a trouble with the circular progressBar, I have it in background in a layout as invisible. When I want to start the new activity I show it setting visible the layout, it is shown good but the animation of the progressBar works bad it sometimes rotate a little then stop after rotate a little more... It isn't fluently. I try to solve with this but seems that didnt work:
button2.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
progressBar.setIndeterminate(true);
progressLayout.setVisibility(View.VISIBLE);
final CustomOverlayItem i = item;
Runnable intentRunnable = new Runnable()
{
public void run()
{
Intent intent = new Intent(context,Next.class);
startActivityForResult(intent, RETURN_FROM_MONUMENTO);
}
};
intentRunnable.run();
}
});
Thanks for your answers.
The part where you receive the data back from the other activity would be interesting. Sending the intent in a Runnable shouldn't be necessary since that is a pretty inexpensive operation (I think). But receiving the result back can result in some heavy operations.
Stuttering animations are normally a sign that you are doing something on the UIThread you shouldn't be doing (or that the device simply is too slow to handle the load of all threads).
If you are doing the network related stuff in the next activity you launch. use AsyncTask in that so that will not block the UI thread and it will make the ProgressBar Animation Smooth.

Show progress Dialog while the UI gets customized

I already have idea on how to use a Progress Dialog when background action is being performed. But my question is how do I show a progress Dialog when I am dynamically inflating a huge layout.
Since I can't inflate a view in another Thread, I am using the main UI thread. Due to this my progress dialog is not getting priority and it doesn't show up. My UI hangs for several seconds until it gets loaded fully. I tried several approcahes but none seems to work.
progress.show(context,"","inflating UI...");
setNewContent(R.layout.my_profile,R.id.my_profile_menu_button,R.id.my_profile_all_elements_layout);
populateProfileList(); //Dynamic nested layouts being inflated.
I am basically looking for dynamic layout changes based on user actions. So I dont have any other way other than creating dynamic views. Can anyone suggest me a helpful idea.
I had an similar problem with ui-thread. I wanted to add much views to my layout at runtime, I wanted to show a ProgressDialog to inform the user, that it could take a while. I had tried it with AsyncTask, but the only chance to do this, was to implement my ui-methods into the onPostExecute-Method of AsyncTask. But this just freezes the ProgressDialog, because ProgressDialog even works on ui-thread. I found a solution, maybe not the best, but it works. Before starting ui-action, I show a Toast. Then, I created a Thread with a handler and delayed the execution. After ui-action was done, I showed a new Toast. Delay the thread, gives the Toast enough time to get showed:
Toast.makeText(ActivityContext.this,
R.string.start_message,
Toast.LENGTH_SHORT).show();
final Handler uiHandler = new Handler();
final Thread uiThread = new Thread(new Runnable() {
#Override
public void run() {
uiHandler.postDelayed(new Runnable() {
#Override
public void run() {
yourUIAction();
Toast.makeText(
ActivityContext.this,
R.string.finish_message,
Toast.LENGTH_SHORT).show();
}
}, 100);
}
});
uiThread.start();
You need to use a handler to be able to talk to the UI thread
//in some thread
uiHandler.sendEmptyMessage(1);
...
Handler uiHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
if(msg.what == 1) {
//do somestuff
}
}
};
Using Async Task is much better idea to me, when you have to do something in background, while progress dialog shows up on screen and then when background task completes, update UI... for reference please follow the link...
http://labs.makemachine.net/2010/05/android-asynctask-example/
hope this helps...:-)

Categories

Resources