Categories
discuss

Why is CompletableFuture join/get faster in separate streams than using one stream

For the following program I am trying to figure out why using 2 different streams parallelizes the task and using the same stream and calling join/get on the Completable future makes them take longer time equivalent to as if they were sequentially processed).

public class HelloConcurrency {

    private static Integer sleepTask(int number) {
        System.out.println(String.format("Task with sleep time %d", number));
        try {
            TimeUnit.SECONDS.sleep(number);
        } catch (InterruptedException e) {
            e.printStackTrace();
            return -1;
        }
        return number;
    }

    public static void main(String[] args) {
        List<Integer> sleepTimes = Arrays.asList(1,2,3,4,5,6);
        System.out.println("WITH SEPARATE STREAMS FOR FUTURE AND JOIN");
        ExecutorService executorService = Executors.newFixedThreadPool(6);
        long start = System.currentTimeMillis();
        List<CompletableFuture<Integer>> futures = sleepTimes.stream()
                .map(sleepTime -> CompletableFuture.supplyAsync(() -> sleepTask(sleepTime), executorService)
                        .exceptionally(ex -> { ex.printStackTrace(); return -1; }))
                .collect(Collectors.toList());
        executorService.shutdown();
        List<Integer> result = futures.stream()
                .map(CompletableFuture::join)
                .collect(Collectors.toList());
        long finish = System.currentTimeMillis();
        long timeElapsed = (finish - start)/1000;
        System.out.println(String.format("done in %d seconds.", timeElapsed));
        System.out.println(result);

        System.out.println("WITH SAME STREAM FOR FUTURE AND JOIN");
        ExecutorService executorService2 = Executors.newFixedThreadPool(6);
        start = System.currentTimeMillis();
        List<Integer> results = sleepTimes.stream()
                .map(sleepTime -> CompletableFuture.supplyAsync(() -> sleepTask(sleepTime), executorService2)
                        .exceptionally(ex -> { ex.printStackTrace(); return -1; }))
                .map(CompletableFuture::join)
                .collect(Collectors.toList());
        executorService2.shutdown();
        finish = System.currentTimeMillis();
        timeElapsed = (finish - start)/1000;
        System.out.println(String.format("done in %d seconds.", timeElapsed));
        System.out.println(results);
    }
}

Output

WITH SEPARATE STREAMS FOR FUTURE AND JOIN
Task with sleep time 6
Task with sleep time 5
Task with sleep time 1
Task with sleep time 3
Task with sleep time 2
Task with sleep time 4
done in 6 seconds.
[1, 2, 3, 4, 5, 6]
WITH SAME STREAM FOR FUTURE AND JOIN
Task with sleep time 1
Task with sleep time 2
Task with sleep time 3
Task with sleep time 4
Task with sleep time 5
Task with sleep time 6
done in 21 seconds.
[1, 2, 3, 4, 5, 6]

Answer

The two approaches are quite different, let me try to explain it clearly

1st approach : In the first approach you are spinning up all Async requests for all 6 tasks and then calling join function on each one of them to get the result

2st approach : But in the second approach you are calling the join immediately after spinning the Async request for each task. For example after spinning Async thread for task 1 calling join, make sure that thread to complete task and then only spin up the second task with Async thread

Note : Another side if you observe the output clearly, In the 1st approach output appears in random order since the all six tasks were executed asynchronously. But during second approach all tasks were executed sequentially one after the another.

I believe you have an idea how stream map operation is performed, or you can get more information from here or here

To perform a computation, stream operations are composed into a stream pipeline. A stream pipeline consists of a source (which might be an array, a collection, a generator function, an I/O channel, etc), zero or more intermediate operations (which transform a stream into another stream, such as filter(Predicate)), and a terminal operation (which produces a result or side-effect, such as count() or forEach(Consumer)). Streams are lazy; computation on the source data is only performed when the terminal operation is initiated, and source elements are consumed only as needed.

Categories
discuss

Android: BroadcastReceiver won’t listen to BOOT_COMPLETED

My app pushes a daily notification (this is working correctly) but after a device reboot notification won’t fire again.

I’m trying to set a BroadcastReceiver that listens to BOOT_COMPLETED to no avail.

AndroidManifest.xml:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
...
<receiver android:name=".helpers.notification.AlarmRebootReceiver"
    android:enabled="false">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

BroadcastReceiver:

public class AlarmRebootReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context oContext, Intent intent) {

        try {    
            Intent notificationIntent = new Intent("android.media.action.DISPLAY_NOTIFICATION");
            notificationIntent.addCategory("android.intent.category.DEFAULT");

            String notificationMessage = TMLocale.getStringResourceByName("reminder_newthought");
            String notificationTitle = TMLocale.getStringResourceByName("app_name");

            TMNotification.Notify(notificationTitle, notificationMessage, Enum.ArtAndWordsNotification.NEWTHOUGHT, oContext);

            TMNotification.cancelNewThoughtAlarm(oContext);
            scheduleNewThoughtAlarm(oContext);
        } catch (Exception e) {
            ExceptionHandler.logException(e);
        }
    }

    private void scheduleNewThoughtAlarm(Context oContext) {

        Calendar cal = Calendar.getInstance();
        int day = cal.get(Calendar.DAY_OF_MONTH);
        int month = cal.get(Calendar.MONTH);
        int year = cal.get(Calendar.YEAR);
        int hour = cal.get(Calendar.HOUR_OF_DAY);
        int minutes = cal.get(Calendar.MINUTE) + 1;
        int seconds = cal.get(Calendar.SECOND);

        Calendar newCalendar = TMDate.generateCalendar(day, month, year, hour, minutes, seconds);
        TMNotification.scheduleNewThoughtAlarm(oContext, newCalendar, null);
    }
}

I set the boot receiver enabled to false in AndroidManifest and set it to true by code when alarm is created, as it suggest in official docs (this is so you listen to boot completed only when needed).

Where notification is launched:

private static void doNewThoughtSchedule(Context oContext, int reminderPreference, boolean randomNotificationsPreference,
                                             Calendar calendar, Intent notificationIntent){

    ComponentName receiver = new ComponentName(ApplicationContext.get(), AlarmRebootReceiver.class);
    PackageManager pm = ApplicationContext.get().getPackageManager();

    pm.setComponentEnabledSetting(receiver,
            PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
            PackageManager.DONT_KILL_APP);

    ...
}

Apparently everythings fine in code but rebooting the device won’t push notification again.

Tried in a Huawei Android 9 device as well as an older Android 4.4 phone. None worked.

Any help?

PS. TMNotification.scheduleNewThoughtAlarm method is irrelevant as it is working fine (setting a simple toast won’t even show in onReceive).

PS2. It’s weird, but following exactly the official docs here doesn’t wort either: https://developer.android.com/training/scheduling/alarms.html#java (where title is “Start an alarm when the device restarts”).

Answer

There might be restriction with setting up several intent-filer action. So change you defining to the next.

<!-- Don't forget about permission -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>


<!-- ... -->
<receiver android:name=".helpers.notification.AlarmRebootReceiver"
    android:permission="android.permission.RECEIVE_BOOT_COMPLETED">

            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>
</receiver>

For all other intent filters use separate Receiver. Now you could receive events in the your method. Just print logs, to ensure the even is coming. And few devices to check it’s not a device specific.

public class AlarmRebootReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context oContext, Intent intent) {
           Log.d("", "Event Received");
           /**
            * .....
            **/
    }
}
Categories
discuss

Android Accessibility – unable to announce TextViews as a Header or link

I have some TextViews that I would like to announce as a header or a link in Talkback mode. Currently, it just announces the text inside the TextView, but I would like it to say “Heading” afterwards, or “link” depending on the TextView. For example, I would like Talkback mode to announce “Log in – heading” rather than just “Log in”.

What I have tried so far is adding this in my Activity‘s onCreate():

ViewCompat.setAccessibilityDelegate(v, new AccessibilityDelegateCompat() {
        @Override
        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) {
            super.onInitializeAccessibilityNodeInfo(host, info);
            info.setHeading(true);
        }
    });

In Talkback mode, there is no change – it still just announces “log in”.

What I notice is that this method, onInitializeAccessibilityNodeInfo, is being called multiple times. When I step through in debugger, every time this method is triggered it shows that isHeading() is false, then set to true.

Am I using this method incorrectly? Why is it called many times? Why is info.setHeading(true) basically ignored?

How would I accomplish something similar, but with Talkback mode announcing “Label – Link” instead of header?

Answer

I have solved my issue!

The issue is that the TextView itself is not getting the focus. Instead, the container view, in this case the FrameLayout that wraps the TextView, was getting focus. That’s why setting the TextView itself as a header was not appearing to work – the view around it was getting the focus.

So given the xml layout:

<FrameLayout
    android:id="@+id/fl_login_header"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:focusableInTouchMode="true" >
        ...
        <TextView
            android:id="@+id/tv_login_header"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/login_sign_in_to_your_account" />
        </FrameLayout>

There are two solutions:

API 28+:

<FrameLayout
    ...
    android:accessibilityHeading="true" >

or, in code, you can do the same thing as in my original question:

ViewCompat.setAccessibilityDelegate(v, new AccessibilityDelegateCompat() {
    @Override
    public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) {
        super.onInitializeAccessibilityNodeInfo(host, info);
        info.setHeading(true);
    }
});

BUT you pass the container view in instead of the TextView.

Categories
discuss

Why can’t “hasOwnProperty” be used on instanceof HTMLInputElement?

I want to check if an input element is a checkbox or text type.

I know I can do this:

//Type of input..
if ( input.type === "checkbox" ) 
//Contains the property..
if ( "checked" in input ) 

But my question is: why do hasOwnProperty returns false?

I just want to use:

input.hasOwnProperty("checked")

but it returns false everytime.

Isn’t input an object?
I don’t think so, but typeof said it is:

typeof input // returns "object" 

So what is going on?!

Code example:

const input = document.querySelector("input")
 if ( input instanceof HTMLInputElement ) {
    console.dir(input);
    console.info(typeof input);
    console.log("with 'hasOwnProperty'",input.hasOwnProperty("checked"));
    console.log("with 'in'","checked" in input);
    console.log("with 'type'",input.type === "checkbox");
}
<input type="checkbox" />

The documentation about HTMLInputElement, only type checkbox have the property checked:

Answer

"checked" in input returns true because in evaluates all enumerable properties. On the contrary, .hasOwnProperty() will return true only if the property is a member of the object itself. It returns false if it’s inherited or a member of the object’s prototype.

In this case, checked is a getter on the HTMLInputElement.prototype, not a member of input.

const checkbox = document.getElementById("c");
const descriptor = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'checked');

console.log("'checked' is property of input:", "checked" in checkbox);
console.log("'checked' is own-property of input:", checkbox.hasOwnProperty("checked"));
console.log("'checked' is member of prototype:", HTMLInputElement.prototype.hasOwnProperty("checked"));
console.log("'checked' is getter:", descriptor.get !== undefined);
<input type="checkbox" id="c">
Categories
discuss

How to unmount inactive screens in bottom tab navigator react-navigation?

Im using react-navigation for react-native. Is there an option to make that inactive tab screens get unmounted like unmountInactiveRoutes: true in DrawerNavigator?? I cant find something like unmountInactiveRoutes for BottomTabNavigator.

I have two stacknavigators inside a BottomTabNavigator and I want to unmount them automatically.

  • BottomTabNavigator
    • Stack1
      • Screen
      • Screen
    • Stack2
      • Screen
      • Screen

Answer

So I don’t know if you can unmount components that are inactive personally I did not find it however this is my workaround withNavigationFocus(FocusStateLabel)
and if isFocused is false. returning null. So this will give you more or less what you are looking for. If isFocused is true, you’ll render what you usually render. If false you’ll return null. resulting in the unmounting of your components

Some reference https://reactnavigation.org/docs/en/with-navigation-focus.html

Source: stackoverflow
Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Privacy Policy, and Copyright Policy. Content is available under CC BY-SA 3.0 unless otherwise noted. The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 © No Copyrights, All Questions are retrived from public domain..