Is there a better way to do this? This is for a Kegel app I'm making, nobody wants the drips when they get older, right?! I've tried using this in a for loop, but it only cycles once. :( Now I'm just typing more because the site won't let me post because it says it looks like my post is mostly code.
public final void onClick(View view) {
switch (view.getId()) {
case R.id.tvBeginner:
tvBeginner.setText("Beginner exercise in progress...");
Runnable clenchRunnable = new Runnable() {
#Override
public void run() {
try {
tvExpert.setText("");
tvIntermediate.setText("Clench!!!");
tvIntermediate.setTextSize(60);
vibrate.vibrate(250);
clenchDone = true;
} catch (Exception e) {
e.printStackTrace();
}
}
};
Runnable relaxRunnable = new Runnable() {
#Override
public void run() {
try {
tvIntermediate.setText("");
tvExpert.setText("Relax...");
tvExpert.setTextSize(40);
tvExpert.setTextColor(Color.GREEN);
vibrate.vibrate(250);
clenchDone = false;
} catch (Exception e) {
e.printStackTrace();
}
}
};
clenchHandler.postDelayed(clenchRunnable, 1000);
relaxHandler.postDelayed(relaxRunnable, 2000);
clenchHandler.postDelayed(clenchRunnable, 3000);
relaxHandler.postDelayed(relaxRunnable, 4000);
clenchHandler.postDelayed(clenchRunnable, 5000);
relaxHandler.postDelayed(relaxRunnable, 6000);
clenchHandler.postDelayed(clenchRunnable, 7000);
relaxHandler.postDelayed(relaxRunnable, 8000);
clenchHandler.postDelayed(clenchRunnable, 9000);
relaxHandler.postDelayed(relaxRunnable, 10000);
clenchHandler.postDelayed(clenchRunnable, 11000);
relaxHandler.postDelayed(relaxRunnable, 12000);
clenchHandler.postDelayed(clenchRunnable, 13000);
relaxHandler.postDelayed(relaxRunnable, 14000);
clenchHandler.postDelayed(clenchRunnable, 15000);
relaxHandler.postDelayed(relaxRunnable, 16000);
clenchHandler.postDelayed(clenchRunnable, 17000);
relaxHandler.postDelayed(relaxRunnable, 18000);
clenchHandler.postDelayed(clenchRunnable, 19000);
relaxHandler.postDelayed(relaxRunnable, 20000);
break;
You could call the relaxHandler, clenchHandler inside their respective runnables and keep a counter of the number of times you want to call it ie:
int i =0;
Runnable relaxRunnable = new Runnable() {
#Override
public void run() {
try {
tvIntermediate.setText("");
tvExpert.setText("Relax...");
tvExpert.setTextSize(40);
tvExpert.setTextColor(Color.GREEN);
vibrate.vibrate(250);
clenchDone = false;
} catch (Exception e) {
e.printStackTrace();
}
if(i <= numTimesToRun) {
relaxHandler.postDelayed(relaxRunnable, time_out_variable);
i++;
}
}
};
and then do the same with the clenchHandler so it runs x amount of times
In the mood for coding, so I'm going to take a crack at it...
private static final int SWITCH_DELAY = 1000;
private Handler handler;
private boolean beginnerCycleActive = false;
private boolean clenched = false;
public final void onClick(View view) {
switch (view.getId()) {
case R.id.tvBeginner:
startBeginnerCycle();
break;
}
}
private void startBeginnerCycle(){
beginnerCycleActive = true;
tvBeginner.setText("Beginner exercise in progress...");
doCycle();
}
private void stopBeginnerCycle(){
beginnerCycleActive = false;
}
private void doCycle(){
onClench();
handler.postDelayed(new Runnable(){
public void run(){
onRelax();
handler.postDelayed(new Runnable(){
public void run(){
if(beginnerCycleActive) doCycle();
}
}, SWITCH_DELAY);
}
}, SWITCH_DELAY);
}
private void onClench(){
try {
tvExpert.setText("");
tvIntermediate.setText("Clench!!!");
tvIntermediate.setTextSize(60);
vibrate.vibrate(250);
clenched = true;
}
catch (Exception e) {
e.printStackTrace();
}
}
private void onRelax(){
try {
tvIntermediate.setText("");
tvExpert.setText("Relax...");
tvExpert.setTextSize(40);
tvExpert.setTextColor(Color.GREEN);
vibrate.vibrate(250);
clenched = false;
}
catch (Exception e) {
e.printStackTrace();
}
}
Much cleaner to look at with no repetition and can easily be stopped by calling stopBeginnerCycle()
You should take a look at ScheduledThreadPoolExecutor. It can be use to run Runnable at fixed time with looop period. Example below will show you how it work.
class YourRunnable implements Runnable {
#Override
public void run() {
//Do your stuff
}
}
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
long period = 10000; // the period between successive executions
exec.scheduleAtFixedRate(new YourRunnable (), 0, duration, TimeUnit.MICROSECONDS); // It can be seconds, miliseconds...
I think it's very easy to use ScheduledThreadPoolExecutor in your case.
Call postDelayed again in the runnable.
Related
What I have tried is that I used volley request to scrape from first website and inside it I created multiple threads for each website and inside each thread I used jsoup connect method to scrape rather than volley. It gets the job done, actually faster. But, what the problem is that it freezes the app when scraping the data until it's fully loaded. It freezes the progress bar and I am having problem to find the cause.
Here's the code I have implemented. It's a bit lengthy.
// Checking the connection
final StringRequest request = new StringRequest("https://www.google.com/", new Response.Listener<String>() {
#Override
public void onResponse(String response) {
relativeLayout.setVisibility(View.GONE);
// instances for each required website
final HimalayanTimes himalayanTimes = new HimalayanTimes(getContext());
final GsmArena gsmArena = new GsmArena();
final CinemaBlend cinemaBlend = new CinemaBlend();
final KathmanduPost kathmanduPost = new KathmanduPost(getContext());
final GlobalNews globalNews = new GlobalNews();
final NepaliTimes nepaliTimes = new NepaliTimes(getContext());
final GoalNepal goalNepal = new GoalNepal(getContext());
final GadgetByte gadgetByte = new GadgetByte();
final TechLekh techLekh = new TechLekh();
final OnlineKhabar onlineKhabar = new OnlineKhabar();
final NepaliSansar nepaliSansar = new NepaliSansar();
final CricketingNepal cricketingNepal = new CricketingNepal();
// thread for each website
// thread fot thehimalayantimes
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
ArrayList<NewsItem> himalyannews;
himalyannews = himalayanTimes.getNews();
news.addAll(himalyannews);
for(int i=0; i<4; i++){
finalHeadlines.add(himalyannews.get(i));
}
} catch (Exception ignored) {
}
}
});
thread.start();
// thread for gsmArena
Thread thread1 = new Thread(new Runnable() {
#Override
public void run() {
try {
ArrayList<NewsItem> gsmarenanews;
gsmarenanews = gsmArena.getNews();
news.addAll(gsmarenanews);
for(int i=0; i<3; i++){
headlines.add(gsmarenanews.get(i));
}
} catch (Exception ignored) {
}
}
});
thread1.start();
// thread for cinemaBlend
Thread thread2 = new Thread(new Runnable() {
#Override
public void run() {
try {
ArrayList<NewsItem> cinemablendnews;
cinemablendnews = cinemaBlend.getNews();
news.addAll(cinemablendnews);
for(int i=0; i<4; i++){
headlines.add(cinemablendnews.get(i));
}
} catch (Exception ignored) {
}
}
});
thread2.start();
// thread for kathmanduPost
Thread thread3 = new Thread(new Runnable() {
#Override
public void run() {
try {
ArrayList<NewsItem> kathmandupostnews;
kathmandupostnews = kathmanduPost.getNews();
news.addAll(kathmandupostnews);
for(int i=0; i<3; i++){
finalHeadlines.add(kathmandupostnews.get(i));
}
} catch (IOException ignored) {
}
}
});
thread3.start();
// thread for globalNews
Thread thread4 = new Thread(new Runnable() {
#Override
public void run() {
try {
ArrayList<NewsItem> globalnewsnews;
globalnewsnews = globalNews.getNews();
news.addAll(globalnewsnews);
for(int i=0; i<5; i++){
finalHeadlines.add(globalnewsnews.get(i));
}
} catch (IOException ignored) {
}
}
});
thread4.start();
// thread for nepaliTimes
Thread thread5 = new Thread(new Runnable() {
#Override
public void run() {
try {
ArrayList<NewsItem> nepalitimesnews;
nepalitimesnews = nepaliTimes.getNews();
news.addAll(nepalitimesnews);
for(int i=0; i<3; i++){
finalHeadlines.add(nepalitimesnews.get(i));
}
} catch (IOException ignored) {
}
}
});
thread5.start();
// thread for GoalNepal
Thread thread6 = new Thread(new Runnable() {
#Override
public void run() {
try {
ArrayList<NewsItem> goalNepalNews;
goalNepalNews = goalNepal.getNews();
news.addAll(goalNepalNews);
for (int i=0; i<4; i++){
headlines.add(goalNepalNews.get(i));
}
} catch (IOException ignored) {
}
}
});
thread6.start();
// thread for GadgetByteNepal
Thread thread7 = new Thread(new Runnable() {
#Override
public void run() {
try {
ArrayList<NewsItem> gadgetbytenews;
gadgetbytenews = gadgetByte.getNews();
news.addAll(gadgetbytenews);
for (int i=0; i<3; i++){
headlines.add(gadgetbytenews.get(i));
}
} catch (IOException ignored) {
}
}
});
thread7.start();
// thread for Techlekh
Thread thread8 = new Thread(new Runnable() {
#Override
public void run() {
try {
ArrayList<NewsItem> techlekhnews;
techlekhnews = techLekh.getNews();
news.addAll(techlekhnews);
for (int i=0; i<3; i++){
headlines.add(techlekhnews.get(i));
}
} catch (IOException ignored) {
}
}
});
thread8.start();
// thread for onlinekhabar
Thread thread9 = new Thread(new Runnable() {
#Override
public void run() {
try {
ArrayList<NewsItem> onlineKhabarnews;
onlineKhabarnews = onlineKhabar.getNews();
news.addAll(onlineKhabarnews);
for (int i=0; i<4; i++){
finalHeadlines.add(onlineKhabarnews.get(i));
}
} catch (IOException ignored) {
}
}
});
thread9.start();
//thread for nepalisansar
Thread thread11 = new Thread(new Runnable() {
#Override
public void run() {
try {
ArrayList<NewsItem> nepalisansarnews;
nepalisansarnews = nepaliSansar.getNews();
news.addAll(nepalisansarnews);
for (int i=0; i<4; i++){
finalHeadlines.add(nepalisansarnews.get(i));
}
} catch (IOException ignored) {
}
}
});
thread11.start();
// thread for cricketingNepal
Thread thread12 = new Thread(new Runnable() {
#Override
public void run() {
try {
ArrayList<NewsItem> cricketnews;
cricketnews = cricketingNepal.getNews();
news.addAll(cricketnews);
for (int i=0; i<4; i++){
headlines.add(cricketnews.get(i));
}
} catch (IOException ignored) {
}
}
});
thread12.start();
// main thread wait for each thread to finish
try {
thread.join();
} catch (InterruptedException ignored) {
}
try {
thread1.join();
} catch (InterruptedException ignored) {
}
try {
thread2.join();
} catch (InterruptedException ignored) {
}
try {
thread3.join();
} catch (InterruptedException ignored) {
}
try {
thread4.join();
} catch (InterruptedException ignored) {
}
try {
thread5.join();
} catch (InterruptedException ignored) {
}
try {
thread6.join();
} catch (InterruptedException ignored) {
}
try {
thread7.join();
} catch (InterruptedException ignored) {
}
try {
thread8.join();
} catch (InterruptedException ignored) {
}
try {
thread8.join();
} catch (InterruptedException ignored) {
}
try {
thread9.join();
} catch (InterruptedException ignored) {
}
try {
thread11.join();
} catch (InterruptedException ignored) {
}
try {
thread12.join();
} catch (InterruptedException ignored) {
}
for(NewsItem item : news){
if (item.tag.contains("kathmandu"))
nepal.add(item);
if (item.tag.contains("cricket"))
sports.add(item);
if (item.tag.contains("football"))
sports.add(item);
switch (item.tag) {
case "nepal":
nepal.add(item);
break;
case "world":
world.add(item);
break;
case "sports":
sports.add(item);
break;
case "tech":
tech.add(item);
break;
case "entertainment":
entertainment.add(item);
break;
}
}
// putting each news item to the main container
Collections.shuffle(headlines);
Collections.shuffle(finalHeadlines);
finalHeadlines.addAll(headlines);
Collections.shuffle(nepal);
Collections.shuffle(world);
Collections.shuffle(sports);
Collections.shuffle(tech);
Collections.shuffle(entertainment);
tab1 t1 = new tab1(finalHeadlines);
t1.setRetainInstance(true);
tab2 t2 = new tab2(nepal);
t2.setRetainInstance(true);
tab3 t3 = new tab3(world);
t3.setRetainInstance(true);
tab4 t4 = new tab4(sports);
t4.setRetainInstance(true);
tab5 t5 = new tab5(tech);
t5.setRetainInstance(true);
tab6 t6 = new tab6(entertainment);
t6.setRetainInstance(true);
assert getFragmentManager() != null;
pagerAdapter = new PageAdapter(finalHeadlines, nepal, world, sports, tech, entertainment, getFragmentManager(), tabLayout.getTabCount());
viewPager.setAdapter(pagerAdapter);
shimmerFrameLayout.setVisibility(View.GONE);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getContext(), "Internet Connection Error!", Toast.LENGTH_SHORT).show();
shimmerFrameLayout.setVisibility(View.GONE);
tabLayout.setVisibility(View.GONE);
}
});
queue.add(request);
For each website, I made class. One of the following class:-
public class CinemaBlend {
ArrayList<NewsItem> news;
public CinemaBlend() {
news = new ArrayList<>();
}
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
public ArrayList<NewsItem> getNews() throws IOException{
String url = "https://www.cinemablend.com/news.php";
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url(url).get().build();
Document document = Jsoup.parse(Objects.requireNonNull(okHttpClient.newCall(request).execute().body()).string());
Elements articles = document.select("div.order-of-type-2").select("div.story-related").select("a");
for(Element article : articles)
{
String link = article.attr("href");
String title = article.attr("title");
String img = article.select("div.story-related-content").select("span.story-cover-image").select("img").attr("data-src");
String date = article.select("span.story-related-published-date").text();
NewsItem newsItem = new NewsItem();
newsItem.imgsrc = img;
newsItem.title = title;
newsItem.link = link;
newsItem.tag = "entertainment";
newsItem.publisher = "cinemablend.com";
newsItem.source_logo = "https://image.pitchbook.com/WFQVGYL17V0MevlcfQKlWjC3E8K1447542818374_200x200";
if(!date.equals(""))
{
newsItem.date = date + " ago";
news.add(newsItem);
}
}
return news;
}
}
Look for tutorials explaining how to perform background work. There are lots of different ways to do that: Service, Kotlin Coroutines, simple self-managed Threads, etc.
Just stay away from tutorials about AsyncTasks and Loaders (deprecated).
A good starting point is the Android developer guide: https://developer.android.com/guide/background
But doing the tasks in Async task create another similar problem. When I create similar threads in background, exactly the similar problem arises where it skips the data and the ui doesn't get updated. Any suggestion would be greatly appreciated.
public class DownloadNews extends AsyncTask<Void, Void, Void>
{
#Override
protected void onPreExecute() {
shimmerFrameLayout.setVisibility(View.VISIBLE);
relativeLayout.setVisibility(View.GONE);
tabLayout.setVisibility(View.GONE);
}
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
#Override
protected Void doInBackground(Void... voids) {
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
final RequestQueue queue = Volley.newRequestQueue(Objects.requireNonNull(getContext()));
// Checking the connection
final StringRequest request = new StringRequest("https://www.google.com/", new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// instances for each required website
final HimalayanTimes himalayanTimes = new HimalayanTimes(getContext());
final GsmArena gsmArena = new GsmArena();
final CinemaBlend cinemaBlend = new CinemaBlend();
final KathmanduPost kathmanduPost = new KathmanduPost(getContext());
final GlobalNews globalNews = new GlobalNews();
final NepaliTimes nepaliTimes = new NepaliTimes(getContext());
final GoalNepal goalNepal = new GoalNepal(getContext());
final GadgetByte gadgetByte = new GadgetByte();
final TechLekh techLekh = new TechLekh();
final OnlineKhabar onlineKhabar = new OnlineKhabar();
final NepaliSansar nepaliSansar = new NepaliSansar();
final CricketingNepal cricketingNepal = new CricketingNepal();
// thread for each website
// thread fot thehimalayantimes
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
himalyannews = himalayanTimes.getNews();
news.addAll(himalyannews);
for(int i=0; i<4; i++){
finalHeadlines.add(himalyannews.get(i));
}
} catch (Exception ignored) {
}
}
});
thread.start();
// thread for gsmArena
Thread thread1 = new Thread(new Runnable() {
#Override
public void run() {
try {
gsmarenanews = gsmArena.getNews();
news.addAll(gsmarenanews);
for(int i=0; i<3; i++){
headlines.add(gsmarenanews.get(i));
}
} catch (Exception ignored) {
}
}
});
thread1.start();
// thread for cinemaBlend
Thread thread2 = new Thread(new Runnable() {
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
#Override
public void run() {
try {
cinemablendnews = cinemaBlend.getNews();
news.addAll(cinemablendnews);
for(int i=0; i<4; i++){
headlines.add(cinemablendnews.get(i));
}
} catch (Exception ignored) {
}
}
});
thread2.start();
// thread for kathmanduPost
Thread thread3 = new Thread(new Runnable() {
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
#Override
public void run() {
try {
kathmandupostnews = kathmanduPost.getNews();
news.addAll(kathmandupostnews);
for(int i=0; i<3; i++){
finalHeadlines.add(kathmandupostnews.get(i));
}
} catch (IOException ignored) {
}
}
});
thread3.start();
// thread for globalNews
Thread thread4 = new Thread(new Runnable() {
#Override
public void run() {
try {
globalnewsnews = globalNews.getNews();
news.addAll(globalnewsnews);
for(int i=0; i<5; i++){
finalHeadlines.add(globalnewsnews.get(i));
}
} catch (IOException ignored) {
}
}
});
thread4.start();
// thread for nepaliTimes
Thread thread5 = new Thread(new Runnable() {
#Override
public void run() {
try {
nepalitimesnews = nepaliTimes.getNews();
news.addAll(nepalitimesnews);
for(int i=0; i<3; i++){
finalHeadlines.add(nepalitimesnews.get(i));
}
} catch (IOException ignored) {
}
}
});
thread5.start();
// thread for GoalNepal
Thread thread6 = new Thread(new Runnable() {
#Override
public void run() {
try {
goalNepalNews = goalNepal.getNews();
news.addAll(goalNepalNews);
for (int i=0; i<4; i++){
headlines.add(goalNepalNews.get(i));
}
} catch (IOException ignored) {
}
}
});
thread6.start();
// thread for GadgetByteNepal
Thread thread7 = new Thread(new Runnable() {
#Override
public void run() {
try {
gadgetbytenews = gadgetByte.getNews();
news.addAll(gadgetbytenews);
for (int i=0; i<3; i++){
headlines.add(gadgetbytenews.get(i));
}
} catch (IOException ignored) {
}
}
});
thread7.start();
// thread for Techlekh
Thread thread8 = new Thread(new Runnable() {
#Override
public void run() {
try {
techlekhnews = techLekh.getNews();
news.addAll(techlekhnews);
for (int i=0; i<3; i++){
headlines.add(techlekhnews.get(i));
}
} catch (IOException ignored) {
}
}
});
thread8.start();
// thread for onlinekhabar
Thread thread9 = new Thread(new Runnable() {
#Override
public void run() {
try {
onlineKhabarnews = onlineKhabar.getNews();
news.addAll(onlineKhabarnews);
for (int i=0; i<4; i++){
finalHeadlines.add(onlineKhabarnews.get(i));
}
} catch (IOException ignored) {
}
}
});
thread9.start();
//thread for nepalisansar
Thread thread11 = new Thread(new Runnable() {
#Override
public void run() {
try {
nepalisansarnews = nepaliSansar.getNews();
news.addAll(nepalisansarnews);
for (int i=0; i<4; i++){
finalHeadlines.add(nepalisansarnews.get(i));
}
} catch (IOException ignored) {
}
}
});
thread11.start();
// thread for cricketingNepal
Thread thread12 = new Thread(new Runnable() {
#Override
public void run() {
try {
cricketnews = cricketingNepal.getNews();
news.addAll(cricketnews);
for (int i=0; i<4; i++){
headlines.add(cricketnews.get(i));
}
} catch (IOException ignored) {
}
}
});
thread12.start();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getContext(), "Internet Connection Error!", Toast.LENGTH_SHORT).show();
shimmerFrameLayout.setVisibility(View.GONE);
relativeLayout.setVisibility(View.VISIBLE);
tabLayout.setVisibility(View.GONE);
}
});
queue.add(request);
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
tabLayout.setVisibility(View.VISIBLE);
shimmerFrameLayout.setVisibility(View.GONE);
for(NewsItem item : news){
if (item.tag.contains("kathmandu"))
nepal.add(item);
switch (item.tag) {
case "nepal":
nepal.add(item);
break;
case "world":
world.add(item);
break;
case "sports":
sports.add(item);
break;
case "tech":
tech.add(item);
break;
case "entertainment":
entertainment.add(item);
break;
}
}
// putting each news item to the main container
Collections.shuffle(headlines);
Collections.shuffle(finalHeadlines);
finalHeadlines.addAll(headlines);
Collections.shuffle(nepal);
Collections.shuffle(world);
Collections.shuffle(sports);
Collections.shuffle(tech);
Collections.shuffle(entertainment);
tab1 t1 = new tab1(finalHeadlines);
t1.setRetainInstance(true);
tab2 t2 = new tab2(nepal);
t2.setRetainInstance(true);
tab3 t3 = new tab3(world);
t3.setRetainInstance(true);
tab4 t4 = new tab4(sports);
t4.setRetainInstance(true);
tab5 t5 = new tab5(tech);
t5.setRetainInstance(true);
tab6 t6 = new tab6(entertainment);
t6.setRetainInstance(true);
shimmerFrameLayout.setVisibility(View.GONE);
assert getFragmentManager() != null;
pagerAdapter = new PageAdapter(finalHeadlines, nepal, world, sports, tech, entertainment, getFragmentManager(), tabLayout.getTabCount());
viewPager.setAdapter(pagerAdapter);
}
}
The code for the adapter is exactly similar to above.
I am using a method to instantiate a new Handler object and kicking off a method to do some task in the allocated time. The problem is, this timer is not restarted for each method call and any lingering time is continued with subsequent calls.
I am wondering how to fix this. This is my method:
private void doTask() {
viewModel.getFeedBackMessage().set("Calculating ...");
viewModel.fetchData();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
if (viewModel.getData() == null) {
viewModel.getFeedbackMessage().set("Failure.");
handler.removeCallbacks(this);
handler.postDelayed(this, 90000);
} else {
handler.removeCallbacks(this);
handler.postDelayed(this, 90000);
}
}
}, 90000);
}
Edit:
new Thread(() -> {
int elapsedTime = 0;
while (elapsedTime < 90000) {
try {
Thread.sleep(1000);
} catch (Exception ex) {}
if (currentLocation != null) {
break;
}
elapsedTime += 1000;
}
}).start();
I need to run 2 threads simultaneously (on occasion if both have been requested together) otherwise if either one is requested solo then each thread needs to run on its own. Each thread will be responsible for taking its own unique reading from its own unique transducer (actual hardware), I need each thread to query its transducer until a certain value is detected. If and only if this value is detected should the thread stop and exit.
I also need a way for my software to know without a doubt that both threads have stopped and exited/completed their task and detected their respective values from the hardware. If and only if both threads detect their values should my onFinish() method be called. In my code, I used a third thread to do this monitoring and the use of integer values. The integer variable threadCount is reset to 0 once my onFinish() method is called and so is my boolean shouldRun which is reset to false within the onFinish() method.
Was wondering if my approach is acceptable/sound logically ( please note I havent done the logic yet for the actual query of each transducer (likely will use a while loop)) also what are the consequences for using the approach I described, my code is as seen below:
private void decreaseThreadCount(){
threadCount -=1;
}
boolean shouldRun = false;
int threadCount = 0;
public void onStart() {
System.out.println("START");
System.out.println(" ");
System.out.println("START PROGRESS BAR");
if((customProgressBarL != null || customProgressBarR != null) || (customProgressBarL != null && customProgressBarR != null)){
shouldRun = true;
}
/**TESTING PURPOSES*/
if (customProgressBarL != null) {
threadCount += 1;
new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i <= 100; i++) {
try {
customProgressBarL.updateProgress(i);
customProgressBarL.repaint();
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(5);
decreaseThreadCount();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}
if (customProgressBarR != null) {
threadCount += 1;
new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i <= 100; i++) {
try {
customProgressBarR.updateProgress(i);
customProgressBarR.repaint();
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//System.out.println("Thread Count: " + threadCount);
try {
Thread.sleep(5);
decreaseThreadCount();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}
new Thread(new Runnable() {
#Override
public void run() {
while(threadCount >= 0 && shouldRun){
try {
System.out.println("Thread Count: " + threadCount);
if(threadCount == 0){
onFinish();
return;
}
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return;
}
}).start();
}
[Edit 1] After reading through the advice given and a bunch of online documentation I have come up with the following code which seems to work under the cases I have tested so far.
Was wondering if I should still use SwingWorkers or if the modified approach is acceptable?
public void onStart() {
System.out.println("START");
System.out.println(" ");
System.out.println("START PROGRESS BAR");
/**TESTING PURPOSES*/
CountDownLatch countDownLatch = new CountDownLatch(2);
new Thread(new Runnable() {
#Override
public void run() {
new Thread(new Runnable() {
#Override
public void run() {
if (customProgressBarL != null) {
for (int i = 0; i <= 100; i++) {
try {
customProgressBarL.updateProgress(i);
customProgressBarL.repaint();
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
countDownLatch.countDown();
return;
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
if(customProgressBarR != null){
for (int i = 0; i <= 100; i++) {
try {
customProgressBarR.updateProgress(i);
customProgressBarR.repaint();
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
countDownLatch.countDown();
return;
}
}).start();
try{
countDownLatch.await();
onFinish();
} catch (InterruptedException e){
e.printStackTrace();
}
}
}).start();
}
[Edit 2]
I have tried a version where I use SwingWorker instead of my Threads, below is the code and it works just as well as the code in [Edit 1] (as far as I can tell at least). What are the pros/cons of each approach?
private class MySwingWorker extends SwingWorker<Object, Object> {
CountDownLatch countDownLatch;
JCustomProgressBar progressBar;
public MySwingWorker(CountDownLatch countDownLatch, JCustomProgressBar progressBar){
this.countDownLatch = countDownLatch;
this.progressBar = progressBar;
}
#Override
protected Object doInBackground() throws Exception {
if(progressBar != null){
for (int i = 0; i <= 100; i++) {
try {
progressBar.updateProgress(i);
progressBar.repaint();
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
countDownLatch.countDown();
return null;
}
}
private class MySwingWorkerManager extends SwingWorker<Object, Object> {
CountDownLatch countDownLatch;
#Override
protected Object doInBackground() throws Exception {
this.countDownLatch = new CountDownLatch(2);
new MySwingWorker(countDownLatch, customProgressBarL).execute();
new MySwingWorker(countDownLatch, customProgressBarR).execute();
try{
countDownLatch.await();
onFinish();
} catch (InterruptedException e){
e.printStackTrace();
}
return null;
}
}
I initiate everything as follows in my onStart() method by calling the execute() method:
public void onStart() {
System.out.println("START");
System.out.println(" ");
System.out.println("START PROGRESS BAR");
System.out.println("customProgressBarL is: "+customProgressBarL);
System.out.println("customProgressBarR is: "+customProgressBarR);
/**TESTING PURPOSES*/
new MySwingWorkerManager().execute();
}
You've initiated all the threads simultanesouly outside (T1,T2,T3) and T3 is waiting for all of them to finish and do some onFinish.
Instead you can instantiate T1 and T2 inside T3.
Create a countdown latch with the number of count.
Decrement the latch count when both the threads finish their task and then execute onFinish().
All the logic to create T1/T2 should be inside T3.
new Thread(new Runnable() {
#Override
public void run() {
int count = 2;
CountdownLatch latch = new CountdownLatch(count);
MyThread t1 = new MyThread(latch);
MyThread t2 = new MyThread(latch);
t1.start()
t2.start();
latch.await();
onFinish();
}
}).start();
Only one thread is supposed to access swing components; you should write something like that:
SwingUtilities.invokeLater(() -> {
customProgressBarR.updateProgress(i);
customProgressBarR.repaint();
});
I would like to ask, if is there a better away to call a method multiple times giving a 5 sec delay between each call.
But I really want is to call the Toas() method about 7 times, and with my code below, it doesnt look right.
Thanks guys
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
CallMultipleToast();
........
private void CallMultipleToast(){
Runnable call_1 = new Runnable() {
#Override
public void run() {
Toast("Message one");
Runnable call_2 = new Runnable() {
#Override
public void run() {
Toast("Message two");
Runnable call_3 = new Runnable() {
#Override
public void run() {
Toast("Message three");
//CAN I ADD MORE
}
};//end call_3
new Handler().postDelayed(call_3, 5000);
}
};//end call_2
new Handler().postDelayed(call_2, 5000);
}
};//end call_1
new Handler().postDelayed(call_1, 5000);
}
private void Toast(String message){
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
}
maybe you can do it like this :
private void CallMultipleToast(){
Thread t = new Thread(){
#Override
public void run(){
try {
for(i=0;i<7;i++){
Toast("Message "+(i+1));
sleep(5000);
}
} catch (InterruptedException ex) {
Log.i("error","thread");
}
}
};
t.start();
}
Try this:
final int DELAY= 5000;
int count = 0;
String[] msgs = {"one", "two", "three", "four", "five"};
Handler handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
if (count < 5) {
Toast(msgs[count]);
handler.post(runnable);
}
count++;
}
};
handler.postDelayed(runnable, DELAY);
Can someone explain me how to refactor the below code. Basically i have a timer functionality which i am using repeatedly. So i want to put that timer into a generic function.
import java.util.Timer;
import java.util.TimerTask;
public class App {
private volatile boolean a = false;
private volatile boolean b = false;
private volatile boolean c = false;
public static void main(String[] args) {
App app = new App();
app.m1();
}
private void m1() {
// m2() should not take more than specified time in timer
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
if(a){
System.out.println("m1 Do nothing");
}
else{
System.out.println("m1 Timeout exception");
}
}
}, 2*60*1000);
a=m2();
System.out.println("Blah");
}
private boolean m2() {
// Killing some time with sleep
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//m3() should not take more than specified time in timer
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
if(b){
System.out.println("m2 Do nothing");
}
else{
System.out.println("m2 Timeout exception");
}
}
}, 1*60*1000);
b = m3();
System.out.println("Blah Blah");
return true;
}
private boolean m3() {
//m4() should not take more than specified time in timer
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
if(c){
System.out.println("m3 Do nothing");
}
else{
System.out.println("m3 Timeout exception");
}
}
}, 20000);
c=m4();
System.out.println("Blah Blah Blah");
return true;
}
private boolean m4() {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
return true;
}
}
Thank you for your help. I am not looking for code help. Want to know your thoughts on minimizing the code.