问:
Placing HBox in BorderPane throws Exception in start method, JavaFX
I am trying to make a layout consisting of a TreeView List and a couple of textfields, buttons at the bottom. I figured i'd use a BorderPane to hold my layout in place. But i am getting an Exception in Application start method and it also tells me Children: duplicate children added: parent = BorderPane@71e344e8

Do you guys have an idea of whats going on?

```<code> public class Main extends Application {

        Stage window;
        TextField nameInput, quantityInput;
        TreeView<String> tree;

        public static void main(String[] args) {
            launch(args);
        }

        public void start (Stage primaryStage) throws Exception{

            window = primaryStage;
            window.setTitle("GrocerieList");

            // tree view
            TreeItem<String> root, food, drink;

            root = new TreeItem<>();
            root.setExpanded(true);

            // food
            food = makeBranch("Food",root);
            makeBranch("Banana", food);
            makeBranch("Coconut", food);
            makeBranch("Eggs", food);

            // drink
            drink = makeBranch("Drinks",root);
            makeBranch("Water", drink);
            makeBranch("Fanta", drink);
            makeBranch("Beer", drink);

            // tree
            tree = new TreeView<>(root);
            tree.setShowRoot(false);

            // bottom input fields
            nameInput = new TextField();
            nameInput.setPromptText("Productname");
            nameInput.setMinWidth(100);

            quantityInput = new TextField();
            quantityInput.setPromptText("Quantity");
            quantityInput.setMinWidth(100);

            // buttons
            Button addbutton = new Button("Add");

            // Layout
            // HBOX
            HBox hBox = new HBox();
            hBox.setPadding(new Insets(10));
            hBox.setSpacing(10);
            hBox.getChildren().addAll(nameInput, quantityInput, addbutton);

            // BorderPane
            BorderPane borderPane = new BorderPane();
            borderPane.getChildren().addAll(tree, hBox);
            borderPane.setCenter(tree);
            borderPane.setBottom(hBox);

            Scene scene = new Scene(borderPane, 520, 620);
            window.setScene(scene);
            window.show();

        }
        public TreeItem<String> makeBranch(String title, TreeItem<String> parent){
            TreeItem<String> item = new TreeItem<>(title);
            item.setExpanded(true);
            parent.getChildren().add(item);
            return item;
        }
</code>```

Complete error:

```<code>    Exception in Application start method
java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
    at java.base/java.lang.Thread.run(Thread.java:830)
Caused by: java.lang.IllegalArgumentException: Children: duplicate children added: parent = BorderPane@71e344e8
    at javafx.graphics/javafx.scene.Parent$3.onProposedChange(Parent.java:560)
    at javafx.base/com.sun.javafx.collections.VetoableListDecorator.add(VetoableListDecorator.java:206)
    at javafx.graphics/javafx.scene.layout.BorderPane$BorderPositionProperty.invalidated(BorderPane.java:692)
    at javafx.base/javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
    at javafx.base/javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:147)
    at javafx.graphics/javafx.scene.layout.BorderPane.setCenter(BorderPane.java:268)
    at sample.Main.start(Main.java:70)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
    at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
Exception running application sample.Main
</code>```

答:
Your problem is here:

BorderPane borderPane = new BorderPane();
borderPane.getChildren().addAll(tree, hBox);
borderPane.setCenter(tree);
borderPane.setBottom(hBox);
```

<p>The calls to <code>setCenter</code> and <code>setBottom</code> add those nodes to the children list. Since you've manually added the two nodes to the children list, those method calls lead to adding the same node to the same parent twice—that's not allowed. When it comes to layouts that provide special properties for positioning, such as <code>BorderPane</code>, you want to avoid interacting with the children list directly. Change your code to:</p>

<pre class="lang-java prettyprint-override"><code>BorderPane borderPane = new BorderPane();
borderPane.setCenter(tree);
borderPane.setBottom(hBox);
</code>```

Body:
I am trying to make a layout consisting of a TreeView List and a couple of textfields, buttons at the bottom. I figured i'd use a BorderPane to hold my layout in place. But i am getting an Exception in Application start method and it also tells me Children: duplicate children added: parent = BorderPane@71e344e8

Do you guys have an idea of whats going on?

 public class Main extends Application {

        Stage window;
        TextField nameInput, quantityInput;
        TreeView<String> tree;

        public static void main(String[] args) {
            launch(args);
        }

        public void start (Stage primaryStage) throws Exception{

            window = primaryStage;
            window.setTitle("GrocerieList");

            // tree view
            TreeItem<String> root, food, drink;

            root = new TreeItem<>();
            root.setExpanded(true);

            // food
            food = makeBranch("Food",root);
            makeBranch("Banana", food);
            makeBranch("Coconut", food);
            makeBranch("Eggs", food);

            // drink
            drink = makeBranch("Drinks",root);
            makeBranch("Water", drink);
            makeBranch("Fanta", drink);
            makeBranch("Beer", drink);

            // tree
            tree = new TreeView<>(root);
            tree.setShowRoot(false);

            // bottom input fields
            nameInput = new TextField();
            nameInput.setPromptText("Productname");
            nameInput.setMinWidth(100);

            quantityInput = new TextField();
            quantityInput.setPromptText("Quantity");
            quantityInput.setMinWidth(100);

            // buttons
            Button addbutton = new Button("Add");

            // Layout
            // HBOX
            HBox hBox = new HBox();
            hBox.setPadding(new Insets(10));
            hBox.setSpacing(10);
            hBox.getChildren().addAll(nameInput, quantityInput, addbutton);

            // BorderPane
            BorderPane borderPane = new BorderPane();
            borderPane.getChildren().addAll(tree, hBox);
            borderPane.setCenter(tree);
            borderPane.setBottom(hBox);

            Scene scene = new Scene(borderPane, 520, 620);
            window.setScene(scene);
            window.show();

        }
        public TreeItem<String> makeBranch(String title, TreeItem<String> parent){
            TreeItem<String> item = new TreeItem<>(title);
            item.setExpanded(true);
            parent.getChildren().add(item);
            return item;
        }

Complete error:

    Exception in Application start method
java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
    at java.base/java.lang.Thread.run(Thread.java:830)
Caused by: java.lang.IllegalArgumentException: Children: duplicate children added: parent = BorderPane@71e344e8
    at javafx.graphics/javafx.scene.Parent$3.onProposedChange(Parent.java:560)
    at javafx.base/com.sun.javafx.collections.VetoableListDecorator.add(VetoableListDecorator.java:206)
    at javafx.graphics/javafx.scene.layout.BorderPane$BorderPositionProperty.invalidated(BorderPane.java:692)
    at javafx.base/javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
    at javafx.base/javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:147)
    at javafx.graphics/javafx.scene.layout.BorderPane.setCenter(BorderPane.java:268)
    at sample.Main.start(Main.java:70)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
    at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
Exception running application sample.Main

Body:
Your problem is here:

BorderPane borderPane = new BorderPane();
borderPane.getChildren().addAll(tree, hBox);
borderPane.setCenter(tree);
borderPane.setBottom(hBox);

The calls to setCenter and setBottom add those nodes to the children list. Since you've manually added the two nodes to the children list, those method calls lead to adding the same node to the same parent twice—that's not allowed. When it comes to layouts that provide special properties for positioning, such as BorderPane, you want to avoid interacting with the children list directly. Change your code to:

BorderPane borderPane = new BorderPane();
borderPane.setCenter(tree);
borderPane.setBottom(hBox);


来源: stackexchange

问:
Compare current time to file date time last modified in Windows Batch File
I would like a command in a batch file to only execute if it has not been ran for the last 15 minutes. To achieve this I can create a "last_run" file to log the time last ran.

Where I am stuck is comparing the time last modified to the current time and taking action if the time last modified.

Here is my current code:

```<code>@echo off
set filename=last_run.txt
if not exist %filename% (
   rem NOT EXISTS, CREATE FILE THEN PRINT THE LIST
   echo.>"%filename%"
   GOTO PrintList
) else (
   rem FILE EXISTS, GET TIME LAST MODIFIED
   FOR %%? IN (%filename%) DO (set filetime=%%~t?)
   echo %filetime%
   rem IF TIME LAST MODIFIED > 15 MINS PRINT THE LIST
   if timediff??(%filetime%, current) > 15 mins {
      GOTO PrintList
   } else {
      GOTO End
   }
)

:PrintList
rem PRINT THE LIST
echo now print the list
rem WRITE TO THE FILE TO UPDATE TIME LAST MODIFIED
echo.>"%filename%"
GOTO End

:End
</code>```

答:
Another implementation using powershell from your batch-file:

@Echo Off
Set "filename=last_run.txt"
Set "minutes=15"
If Not Exist "%filename%" GoTo :PrintList
"%__APPDIR__%WindowsPowerShell\v1.0\powershell.exe" -NoProfile If(((Get-Date)-(Get-Item ".\%filename%").LastWriteTime).Minutes -LT %minutes%){Exit 1}
If ErrorLevel 1 Exit /B
Rem Your payload below here.

:PrintList
CD.>"%filename%"
```

If you are happy to accept that the PC running this code will always have the appropriate entries in %PATH% and %PATHEXT%, you can change "%__APPDIR__%WindowsPowerShell\v1.0\powershell.exe" to just PowerShell.

ContentLicense: CC BY-SA 4.0

Body:
I would like a command in a batch file to only execute if it has not been ran for the last 15 minutes. To achieve this I can create a "last_run" file to log the time last ran.

Where I am stuck is comparing the time last modified to the current time and taking action if the time last modified.

Here is my current code:

@echo off
set filename=last_run.txt
if not exist %filename% (
   rem NOT EXISTS, CREATE FILE THEN PRINT THE LIST
   echo.>"%filename%"
   GOTO PrintList
) else (
   rem FILE EXISTS, GET TIME LAST MODIFIED
   FOR %%? IN (%filename%) DO (set filetime=%%~t?)
   echo %filetime%
   rem IF TIME LAST MODIFIED > 15 MINS PRINT THE LIST
   if timediff??(%filetime%, current) > 15 mins {
      GOTO PrintList
   } else {
      GOTO End
   }
)

:PrintList
rem PRINT THE LIST
echo now print the list
rem WRITE TO THE FILE TO UPDATE TIME LAST MODIFIED
echo.>"%filename%"
GOTO End

:End

Body:
Another implementation using powershell from your batch-file:

@Echo Off
Set "filename=last_run.txt"
Set "minutes=15"
If Not Exist "%filename%" GoTo :PrintList
"%__APPDIR__%WindowsPowerShell\v1.0\powershell.exe" -NoProfile If(((Get-Date)-(Get-Item ".\%filename%").LastWriteTime).Minutes -LT %minutes%){Exit 1}
If ErrorLevel 1 Exit /B
Rem Your payload below here.

:PrintList
CD.>"%filename%"

If you are happy to accept that the PC running this code will always have the appropriate entries in %PATH% and %PATHEXT%, you can change "%__APPDIR__%WindowsPowerShell\v1.0\powershell.exe" to just PowerShell.


问:
Trying to code a complex algorithm with `OrderedDict` data Structure
I am trying to write an algorithm:

i have this input of OrderedDict data type like the following:

```<code>odict_items([(3, [(0, 1), (1, 1), (1, 1)]), (11, [(0, 0), (1, 1), (1, 1)]), (12, [(0, 0), (1, 1), (1, 1)])])
</code>```

I am trying to write a function to added the number of same tuple in the each key for example the expected output like the following: if there is (1,1) same tuple then 1 and if twice the 2 and so one:

```<code>odict_items([(3, [(0, 1), (1, 1), (1, 1)],2), (11, [(0, 0), (1, 1), (1, 1)],2), (12, [(0, 0), (1, 0), (1, 1)]),1])
</code>```

this is my try but how to improve it and add it to the OrderedDict ?

```<code>def foo(OrderedDict):
    listOfDic = list(makeDataStruc().items())
    tupleCounter = 0
    for i in range(len(listOfDic[1])):
        if listOfDic[1][1][i][0] == 1 and listOfDic[1][1][i][1] == 1:
            tupleCounter += 1
    return tupleCounter
</code>```

Where am i making error?

答:
I am making the following assumptions,

You simply want to add the count of (1,1) to the OrderedDict value

You don't want to create a new data structure which overrides the current OrderedDict.

You can modify the original Dictionary

Now based on the information available in the question and the above mentioned assumptions, one possible solution could be to replace every value with a list containing two elements, i.e. `[original value, count of (1, 1)]

```<code>from collections import OrderedDict

odict_items = [(3, [(0, 1), (1, 1), (1, 1)]),
               (11, [(0, 0), (1, 1), (1, 1)]),
               (12, [(0, 0), (1, 1), (1, 1)])]

my_odict = OrderedDict()

for item in odict_items:
    k, v = item
    my_odict[k] = v
</code>```

Now count the occurrence of (1,1) in every value and update the values accordingly

```<code>pattern_to_find = (1, 1)

for key, value in my_odict.items():
    tuple_count = value.count(pattern_to_find)
    new_value = [value, tuple_count]
    my_odict[key] = new_value
</code>```

Now the dictionary has the following contents:

```<code>OrderedDict([(3, [[(0, 1), (1, 1), (1, 1)], 2]),
             (11, [[(0, 0), (1, 1), (1, 1)], 2]),
             (12, [[(0, 0), (1, 1), (1, 1)], 2])])
</code>```

Now you can create additional function to access only the value or tuple count

```<code># Returns the count of (1, 1) only
def get_count(my_dict, key):
    return my_dict[key][1]

# Return the original value only
def get_tuple(my_dict, key):
    return my_dict[key][0]
</code>```

So you can use them like this

```<code>print(my_odict[3])
# [[(0, 1), (1, 1), (1, 1)], 2]

print(get_count(my_odict,3))
# 2

print(get_tuple(my_odict, 3))
# [(0, 1), (1, 1), (1, 1)]
</code>```

Body:
I am trying to write an algorithm:

i have this input of OrderedDict data type like the following:

odict_items([(3, [(0, 1), (1, 1), (1, 1)]), (11, [(0, 0), (1, 1), (1, 1)]), (12, [(0, 0), (1, 1), (1, 1)])])

I am trying to write a function to added the number of same tuple in the each key for example the expected output like the following: if there is (1,1) same tuple then 1 and if twice the 2 and so one:

odict_items([(3, [(0, 1), (1, 1), (1, 1)],2), (11, [(0, 0), (1, 1), (1, 1)],2), (12, [(0, 0), (1, 0), (1, 1)]),1])

this is my try but how to improve it and add it to the OrderedDict ?

def foo(OrderedDict):
    listOfDic = list(makeDataStruc().items())
    tupleCounter = 0
    for i in range(len(listOfDic[1])):
        if listOfDic[1][1][i][0] == 1 and listOfDic[1][1][i][1] == 1:
            tupleCounter += 1
    return tupleCounter

Where am i making error?

Body:
I am making the following assumptions,

You simply want to add the count of (1,1) to the OrderedDict value

You don't want to create a new data structure which overrides the current OrderedDict.

You can modify the original Dictionary

Now based on the information available in the question and the above mentioned assumptions, one possible solution could be to replace every value with a list containing two elements, i.e. `[original value, count of (1, 1)]

from collections import OrderedDict

odict_items = [(3, [(0, 1), (1, 1), (1, 1)]),
               (11, [(0, 0), (1, 1), (1, 1)]),
               (12, [(0, 0), (1, 1), (1, 1)])]

my_odict = OrderedDict()

for item in odict_items:
    k, v = item
    my_odict[k] = v

Now count the occurrence of (1,1) in every value and update the values accordingly

pattern_to_find = (1, 1)

for key, value in my_odict.items():
    tuple_count = value.count(pattern_to_find)
    new_value = [value, tuple_count]
    my_odict[key] = new_value

Now the dictionary has the following contents:

OrderedDict([(3, [[(0, 1), (1, 1), (1, 1)], 2]),
             (11, [[(0, 0), (1, 1), (1, 1)], 2]),
             (12, [[(0, 0), (1, 1), (1, 1)], 2])])

Now you can create additional function to access only the value or tuple count

# Returns the count of (1, 1) only
def get_count(my_dict, key):
    return my_dict[key][1]

# Return the original value only
def get_tuple(my_dict, key):
    return my_dict[key][0]

So you can use them like this

print(my_odict[3])
# [[(0, 1), (1, 1), (1, 1)], 2]

print(get_count(my_odict,3))
# 2

print(get_tuple(my_odict, 3))
# [(0, 1), (1, 1), (1, 1)]


问:
Is there a way to know if an object has a non-iterable NoneType object inside
So I'm using vininfo to populate information about some units from an external DB using their VIN only and to work with this data I am converting it to a dict using annotate() or annotate().items() but the script breaks down on

TypeError: cannot unpack non-iterable NoneType object

Tried using hasattr(obj, 'attr') but it explodes there with the same error. Cannot iterate with a for..in because the object is not an iterable TypeError: 'NoneType' object is not iterable.

I tried on the CLI version with the same VIN and it spits out the same cannot unpack error.

The thing is this VIN I'm using to test is missing some data .transmission to be precise (but I guess it'll happen with any other field), probably due to a misspelling when filling the registration form so I'm trying to ignore this field but I can't because it doesn't exist!

The VIN is: 1NKZXPEX4GJ109010

The Traceback is the following:

Traceback (most recent call last):
  File "c:\program files\python37\lib\runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "c:\program files\python37\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "C:\Program Files\Python37\Scripts\vininfo.exe\__main__.py", line 7, in <module>
  File "c:\program files\python37\lib\site-packages\vininfo\cli.py", line 51, in main
    entry_point(obj={})
  File "c:\program files\python37\lib\site-packages\click\core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "c:\program files\python37\lib\site-packages\click\core.py", line 717, in main
    rv = self.invoke(ctx)
  File "c:\program files\python37\lib\site-packages\click\core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "c:\program files\python37\lib\site-packages\click\core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "c:\program files\python37\lib\site-packages\click\core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "c:\program files\python37\lib\site-packages\vininfo\cli.py", line 35, in show
    out(details)
  File "c:\program files\python37\lib\site-packages\vininfo\cli.py", line 24, in out
    for k, v in annotatable.annotate().items():
  File "c:\program files\python37\lib\site-packages\vininfo\common.py", line 17, in annotate
    value = getattr(self, attr_name, no_attr)
  File "c:\program files\python37\lib\site-packages\vininfo\details\_base.py", line 53, in __get__
    return DetailWrapper(instance, self)
  File "c:\program files\python37\lib\site-packages\vininfo\details\_base.py", line 20, in __init__
    attr_name, attr_idx = detail.source
TypeError: cannot unpack non-iterable NoneType object
```

答:
You can force transmission to an empty list:</p>

```<code>>>> vin = vininfo.Vin("1NKZXPEX4GJ109010")
>>> vin.details.transmission = []
>>> vin.details.annotate()
OrderedDict([('Body', 'E'), ('Engine', 'Z'), ('Model', 'X'), ('Plant', 'J'), ('Serial', '109010'), ('Transmission', '')])
</code>```

Body:
You can force transmission to an empty list:

>>> vin = vininfo.Vin("1NKZXPEX4GJ109010")
>>> vin.details.transmission = []
>>> vin.details.annotate()
OrderedDict([('Body', 'E'), ('Engine', 'Z'), ('Model', 'X'), ('Plant', 'J'), ('Serial', '109010'), ('Transmission', '')])


问:
php in_array usage
I have this code: ids row is like ( 54,88,15,78) a string concat of id:

```<code>$sql = "SELECT *, ids FROM.....";
$results = $Database->Select($sql);
$last = end($results);
foreach($results as $i){
    $userArray = explode(",",$i['ids']);
    if( in_array($_SESSION['AUTH_ID'], $userArray) ){
        echo $i['name'];
        if($last != $i)
            echo ",\n";
    }
}
</code>```

This prints always a comma after $i['name']... this is wrong.. how can i fix it?? How can I count in_array new value??

答:
There is an easier way to do this:

```<code>/* ... */
$logged_in[] = array();
if( in_array($_SESSION['AUTH_ID'], $userArray) ){
    $logged_in[] = $i['name'];
}

echo implode(', ', $logged_in);
</code>```

This prints Alice, Bob

ContentLicense: CC BY-SA 3.0

Title: php in_array usage

Body:
I have this code: ids row is like ( 54,88,15,78) a string concat of id:

$sql = "SELECT *, ids FROM.....";
$results = $Database->Select($sql);
$last = end($results);
foreach($results as $i){
    $userArray = explode(",",$i['ids']);
    if( in_array($_SESSION['AUTH_ID'], $userArray) ){
        echo $i['name'];
        if($last != $i)
            echo ",\n";
    }
}

This prints always a comma after $i['name']... this is wrong.. how can i fix it?? How can I count in_array new value??

Body:
There is an easier way to do this:

/* ... */
$logged_in[] = array();
if( in_array($_SESSION['AUTH_ID'], $userArray) ){
    $logged_in[] = $i['name'];
}

echo implode(', ', $logged_in);

This prints Alice, Bob


问:
Java Garbage Collection problem using Liferay on JBoss: GC executed many times
We are experiencing garbage collection problems in an environment composed of Liferay 6.2 and JBoss 6.4.5.

The server is running smoothly and GC process seams normally well-executed, but at one point the GC process starts executing many times:

We are running in a 16GB memory server with the following memory configuration:

JAVA_OPTS="$JAVA_OPTS -Xms6144m -Xmx6144m -XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=2048m"

No memory leaks are detected.

Could anyone help us explain why the GC behaviors like this?

Thank you very much in advance.

答:
Looking at chart I assume you are using ParallelGC in HotSpot JVM.

ParallelGC is switching from generational (young/old) to single space operation mode if live data set does not fit old space size.

In single space every collection is Full GC.

Solution is to increase old space. It can be done either by increasing heap size or by reducing new size (e.g. -Xmn1g option).


问:
recyclerview notifyDataSetChanged() is not working
I am trying to update myadapter using notifyDataSetchanged() in updateList().But not working for recyclerview. I can able to see list size in updateList() and its displaying actual result but only reclerview is not updating.This class was designed in MVVM Design Pattern.

```<code>   public class TasksAdapter extends RecyclerView.Adapter<TasksAdapter.TasksAdapterViewHolder> {
        private static final String TAG =  TasksAdapter.class.getSimpleName();
        static ArrayList<ItemModel> list;
        static Context mContext;
        private Fragment fragment;
        private int row_index = -1;
        private SessionManager session;
    //    SelectColorVM colorVM;

        public TasksAdapter(Fragment fragment, Context context, ArrayList<ItemModel> itemList) {
            this.mContext = context;
            this.list = itemList;
            this.fragment = fragment;
            session = new SessionManager(fragment.getContext());
        }

        public void updateList(ArrayList<ItemModel> itemList){
            list.clear();
            this.list = itemList;
            notifyDataSetChanged();
        }

        @Override
        public TasksAdapterViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            TasksItemBinding binding =
                    DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.tasks_item,
                            parent, false);
            return new TasksAdapter.TasksAdapterViewHolder(binding);
        }

        @Override
        public void onBindViewHolder(TasksAdapterViewHolder holder, final int position) {
            holder.binding.setViewModel(list.get(position));
            if(position == 0 && list.get(position).btnText.get().toString().length() > 0)
                holder.binding.btnUpdate.setVisibility(View.VISIBLE);
            else
                holder.binding.btnUpdate.setVisibility(View.INVISIBLE);
            holder.binding.layoutItem.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
    //                row_index = position;
    //                notifyDataSetChanged();
                    Fragment fragment = new DetailFragment();
                    FragmentManager manager = ((FragmentActivity) mContext).getSupportFragmentManager();
                    FragmentTransaction fragmentTransaction = manager.beginTransaction();
                    Bundle bundle = new Bundle();
                    ItemModel item = list.get(position);
                    bundle.putSerializable("item", item);
                    fragment.setArguments(bundle);
                    fragmentTransaction.replace(R.id.id_frame, fragment, "details");
                    fragmentTransaction.addToBackStack("details");
                    fragmentTransaction.commit();
                }
            });
            holder.binding.btnUpdate.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    HashMap<String, String> user = session.getUserDetails();
                    if(list.get(position).btnText.get().equals("Task Start")){
                        LandingEngine.updateStatusAndSetStartTimeForRequest(fragment, user.get(SessionManager.KEY_CLEANER_ID), list.get(position).sid.get().toString());
                    } else if(list.get(position).btnText.get().equals("Task Complete")){
                        LandingEngine.updateStatusAndSetCompleteTimeForRequest(fragment, user.get(SessionManager.KEY_CLEANER_ID), list.get(position).sid.get().toString());
                    }
                }
            });
        }

        @Override
        public int getItemCount() {
            return list.size();
        }

        public static class TasksAdapterViewHolder extends RecyclerView.ViewHolder {
            TasksItemBinding binding;

            public TasksAdapterViewHolder(TasksItemBinding rowbinding) {
                super(rowbinding.getRoot());
                this.binding = rowbinding;
            }

        }
        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public int getItemViewType(int position) {
            return position;
        }

    }
</code>```

I am calling adapter from my fragment like below

```<code>if(list.size() > 0) {
            if(adapter == null) {
                view.setHasFixedSize(true);
                mLayoutManager = new LinearLayoutManager(fragment.getContext());
                view.setLayoutManager(mLayoutManager);
                adapter = new TasksAdapter(fragment, fragment.getContext(), list);
                view.setAdapter(adapter);
                view.addItemDecoration(new DividerItemDecoration(fragment.getContext()));
            } else {
                adapter.updateList(list);
//                view.getAdapter().notifyDataSetChanged();
//                view.invalidate();
            }
        }
</code>```

Please check this and let me know where i am doing wrong here.Thanks in advance..

答:
have a same issue. In my case there was error message in the logcat RecyclerView: No layout manager attached; skipping layout

which i have fixed with following code

```<code>    LinearLayoutManager llm = new LinearLayoutManager(this.getActivity());
    llm.setOrientation(LinearLayoutManager.VERTICAL);
    mRecyclerView.setLayoutManager(llm);
</code>```

then the notifyDataSetChanged start work

Body:
I am trying to update myadapter using notifyDataSetchanged() in updateList().But not working for recyclerview. I can able to see list size in updateList() and its displaying actual result but only reclerview is not updating.This class was designed in MVVM Design Pattern.

   public class TasksAdapter extends RecyclerView.Adapter<TasksAdapter.TasksAdapterViewHolder> {
        private static final String TAG =  TasksAdapter.class.getSimpleName();
        static ArrayList<ItemModel> list;
        static Context mContext;
        private Fragment fragment;
        private int row_index = -1;
        private SessionManager session;
    //    SelectColorVM colorVM;

        public TasksAdapter(Fragment fragment, Context context, ArrayList<ItemModel> itemList) {
            this.mContext = context;
            this.list = itemList;
            this.fragment = fragment;
            session = new SessionManager(fragment.getContext());
        }

        public void updateList(ArrayList<ItemModel> itemList){
            list.clear();
            this.list = itemList;
            notifyDataSetChanged();
        }

        @Override
        public TasksAdapterViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            TasksItemBinding binding =
                    DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.tasks_item,
                            parent, false);
            return new TasksAdapter.TasksAdapterViewHolder(binding);
        }

        @Override
        public void onBindViewHolder(TasksAdapterViewHolder holder, final int position) {
            holder.binding.setViewModel(list.get(position));
            if(position == 0 && list.get(position).btnText.get().toString().length() > 0)
                holder.binding.btnUpdate.setVisibility(View.VISIBLE);
            else
                holder.binding.btnUpdate.setVisibility(View.INVISIBLE);
            holder.binding.layoutItem.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
    //                row_index = position;
    //                notifyDataSetChanged();
                    Fragment fragment = new DetailFragment();
                    FragmentManager manager = ((FragmentActivity) mContext).getSupportFragmentManager();
                    FragmentTransaction fragmentTransaction = manager.beginTransaction();
                    Bundle bundle = new Bundle();
                    ItemModel item = list.get(position);
                    bundle.putSerializable("item", item);
                    fragment.setArguments(bundle);
                    fragmentTransaction.replace(R.id.id_frame, fragment, "details");
                    fragmentTransaction.addToBackStack("details");
                    fragmentTransaction.commit();
                }
            });
            holder.binding.btnUpdate.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    HashMap<String, String> user = session.getUserDetails();
                    if(list.get(position).btnText.get().equals("Task Start")){
                        LandingEngine.updateStatusAndSetStartTimeForRequest(fragment, user.get(SessionManager.KEY_CLEANER_ID), list.get(position).sid.get().toString());
                    } else if(list.get(position).btnText.get().equals("Task Complete")){
                        LandingEngine.updateStatusAndSetCompleteTimeForRequest(fragment, user.get(SessionManager.KEY_CLEANER_ID), list.get(position).sid.get().toString());
                    }
                }
            });
        }

        @Override
        public int getItemCount() {
            return list.size();
        }

        public static class TasksAdapterViewHolder extends RecyclerView.ViewHolder {
            TasksItemBinding binding;

            public TasksAdapterViewHolder(TasksItemBinding rowbinding) {
                super(rowbinding.getRoot());
                this.binding = rowbinding;
            }

        }
        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public int getItemViewType(int position) {
            return position;
        }

    }

I am calling adapter from my fragment like below

if(list.size() > 0) {
            if(adapter == null) {
                view.setHasFixedSize(true);
                mLayoutManager = new LinearLayoutManager(fragment.getContext());
                view.setLayoutManager(mLayoutManager);
                adapter = new TasksAdapter(fragment, fragment.getContext(), list);
                view.setAdapter(adapter);
                view.addItemDecoration(new DividerItemDecoration(fragment.getContext()));
            } else {
                adapter.updateList(list);
//                view.getAdapter().notifyDataSetChanged();
//                view.invalidate();
            }
        }

Please check this and let me know where i am doing wrong here.Thanks in advance..

Body:
have a same issue. In my case there was error message in the logcat RecyclerView: No layout manager attached; skipping layout

which i have fixed with following code

    LinearLayoutManager llm = new LinearLayoutManager(this.getActivity());
    llm.setOrientation(LinearLayoutManager.VERTICAL);
    mRecyclerView.setLayoutManager(llm);

then the notifyDataSetChanged start work


问:
How to Read Performance Counters in C++

Which are the classes in C++ to read performance counters.

How to read these counters data.

答:
Accessing Performance Data in C++

Performance Counter Classes

Title: How to Read Performance Counters in C++


问:
How do I install Tkinter for Ubuntu?
I recently installed Ubuntu as my operating system. I tried installing some python modules; it is giving an error. I am running the command sudo apt install python3-tk and the error is:

```<code>E: Malformed entry 1 in list file /etc/apt/sources.list.d/sublime-text.list (Suite)
E: The list of sources could not be read.
E: Malformed entry 1 in list file /etc/apt/sources.list.d/sublime-text.list (Suite)
E: The list of sources could not be read.
</code>```

If you could help, thank you.

答:
There is a slight modification required in the command you used. Can you try,

```<code>sudo apt-get install python3.5-tk
</code>```

instead?

Try sudo apt-get install -qq python-tk

It worked in my case.

For Python 2.7, do

```<code>sudo apt-get install python-tk
</code>```

For Python 3+, do

```<code>sudo apt-get install python3 python3-tk
</code>```

or if you want to remain in Python 2.7, try

```<code>sudo apt-get install python python-tk
</code>```

Title: How do I install Tkinter for Ubuntu?

Body:
I recently installed Ubuntu as my operating system. I tried installing some python modules; it is giving an error. I am running the command sudo apt install python3-tk and the error is:

E: Malformed entry 1 in list file /etc/apt/sources.list.d/sublime-text.list (Suite)
E: The list of sources could not be read.
E: Malformed entry 1 in list file /etc/apt/sources.list.d/sublime-text.list (Suite)
E: The list of sources could not be read.

If you could help, thank you.

Body:
There is a slight modification required in the command you used. Can you try,

sudo apt-get install python3.5-tk

instead?

Try sudo apt-get install -qq python-tk

It worked in my case.

For Python 2.7, do

sudo apt-get install python-tk

For Python 3+, do

sudo apt-get install python3 python3-tk

or if you want to remain in Python 2.7, try

sudo apt-get install python python-tk


问:
JMS message listener invoker failed, Cause: Identifier contains invalid JMS identifier character '-': 'x-request-id'
I'm working with JMS and queues (Azure queues) for the first time. I'm required to make a queue where Rubi server would write some data and Java would read it from queue and will do further executions.
This process is working fine locally on my machine. I've created a REST endpoint which is writing data in the queue and once data is written in the queue, the listener would take over and read the data and execute.
When we deploy it to Azure the error I can see in logs which is not letting the Queues start is

```<code>Setup of JMS message listener invoker failed for destination 'queue' - trying to recover. Cause: Identifier contains invalid JMS identifier character '-': 'x-request-id'
</code>```

Zipkin is also present on the Azure server as a distributed tracing system and I guess this x-request-id is related to Zipkin which is creating the problem. I've searched Google for the issue but couldn't understand why its happening.

Following is detailed error message:

```<code>[36mc.m.s.l.NextGenRequestLoggingFilter     [0;39m [2m:[0;39m
Before request [uri=/services/deal-service/api/v2/deals/ack;headers=
[x-request-id:"2d8d86d7-4fbf-9db6-8e95-28813f21a85c",
x-envoy-internal:"true", x-b3-parentspanid:"a209cdc649b0b890", content-
length:"575", x-forwarded-proto:"http", postman-token:"ad074595-
76a5-474b-9711-7e071b12b3b0", x-b3-sampled:"1", x-forwarded-
for:"10.244.2.1", accept:"*/*",
authorization: "some-token-YJc4tg--34jPRziJNSACqNQ", x-b3-
traceid:"6b40ff22781be67ba209cdc649b0b890", x-b3-
spanid:"702684ddb62cfe6b",
host:"portal-gateway.52.228.65.225.nip.io",
cache-control:"no-cache", accept-encoding:"gzip, deflate, br",
user-agent:"PostmanRuntime/7.22.0",
Content-Type:"application/xml;charset=UTF-8"]]
2020-02-18T15:19:34.197666458Z [2m2020-02-18 15:19:34.197[0;39m  .
[32mDEBUG
[,6b40ff22781be67ba209cdc649b0b890,702684ddb62cfe6b,true][0;39m  .
[35m9[0;39m [2m---[0;39m [2m[ XNIO-1 task-15][0;39m
</code>```

答:
Details of error (Java stack trace) would be really useful here.

By error message I assume, you are using qpid JMS client, that is performing check of message properties' names. These names can contain only characters, that are valid Java identifier characters.

In string 'queue-name' there is a '-' character, that is not Java identifier. To fix, you need to change 'queue-name' into something with valid characters, for example 'queue_name' (with underscore), or 'queueName' (camel case).

Body:
I'm working with JMS and queues (Azure queues) for the first time. I'm required to make a queue where Rubi server would write some data and Java would read it from queue and will do further executions.
This process is working fine locally on my machine. I've created a REST endpoint which is writing data in the queue and once data is written in the queue, the listener would take over and read the data and execute.
When we deploy it to Azure the error I can see in logs which is not letting the Queues start is

Setup of JMS message listener invoker failed for destination 'queue' - trying to recover. Cause: Identifier contains invalid JMS identifier character '-': 'x-request-id'

Zipkin is also present on the Azure server as a distributed tracing system and I guess this x-request-id is related to Zipkin which is creating the problem. I've searched Google for the issue but couldn't understand why its happening.

Following is detailed error message:

[36mc.m.s.l.NextGenRequestLoggingFilter     [0;39m [2m:[0;39m
Before request [uri=/services/deal-service/api/v2/deals/ack;headers=
[x-request-id:"2d8d86d7-4fbf-9db6-8e95-28813f21a85c",
x-envoy-internal:"true", x-b3-parentspanid:"a209cdc649b0b890", content-
length:"575", x-forwarded-proto:"http", postman-token:"ad074595-
76a5-474b-9711-7e071b12b3b0", x-b3-sampled:"1", x-forwarded-
for:"10.244.2.1", accept:"*/*",
authorization: "some-token-YJc4tg--34jPRziJNSACqNQ", x-b3-
traceid:"6b40ff22781be67ba209cdc649b0b890", x-b3-
spanid:"702684ddb62cfe6b",
host:"portal-gateway.52.228.65.225.nip.io",
cache-control:"no-cache", accept-encoding:"gzip, deflate, br",
user-agent:"PostmanRuntime/7.22.0",
Content-Type:"application/xml;charset=UTF-8"]]
2020-02-18T15:19:34.197666458Z [2m2020-02-18 15:19:34.197[0;39m  .
[32mDEBUG
[,6b40ff22781be67ba209cdc649b0b890,702684ddb62cfe6b,true][0;39m  .
[35m9[0;39m [2m---[0;39m [2m[ XNIO-1 task-15][0;39m


问:
Splitting a DynamoDB result into a 2D array in Python
I am trying to split this array in Python that I pulled down from a DynamoDB table into separate chunks so that I can then calculate the Averages of each AssetID, storing the AssetID and the Rating into separate parts of the Array.

```<code>[{'ID': Decimal('0'), 'AssetID': Decimal('0'), 'Rating': Decimal('3')}, {'ID': Decimal('1'), 'AssetID': Decimal('0'), 'Rating': Decimal('5')}]
</code>```

So for example, I would like the array to look like the following:

```<code>AssetIDArray[AssetID][Rating]
</code>```

So hence if I were to print the following, I would get 5.

```<code>AssetIDArray[0][1]
</code>```

Thanks in advance for the help!

答:
You need a dict instead of a list as AssetIDs:</p>

```<code>from decimal import Decimal

items = [{'ID': Decimal('0'), 'AssetID': Decimal('0'), 'Rating': Decimal('3')},
         {'ID': Decimal('1'), 'AssetID': Decimal('0'), 'Rating': Decimal('5')}]

parsed_item_list = {}

for item in items:
    assetId = int(item.get('AssetID'))
    rating = int(item.get('Rating'))
    if assetId not in parsed_item_list:
        parsed_item_list[assetId] = []
    parsed_item_list[assetId].append(rating)

print(parsed_item_list.get(0)[0]) # 3
print(parsed_item_list.get(0)[1]) # 5
</code>```

Body:
I am trying to split this array in Python that I pulled down from a DynamoDB table into separate chunks so that I can then calculate the Averages of each AssetID, storing the AssetID and the Rating into separate parts of the Array.

[{'ID': Decimal('0'), 'AssetID': Decimal('0'), 'Rating': Decimal('3')}, {'ID': Decimal('1'), 'AssetID': Decimal('0'), 'Rating': Decimal('5')}]

So for example, I would like the array to look like the following:

AssetIDArray[AssetID][Rating]

So hence if I were to print the following, I would get 5.

AssetIDArray[0][1]

Thanks in advance for the help!

Body:
You need a dict instead of a list as AssetIDs:

from decimal import Decimal

items = [{'ID': Decimal('0'), 'AssetID': Decimal('0'), 'Rating': Decimal('3')},
         {'ID': Decimal('1'), 'AssetID': Decimal('0'), 'Rating': Decimal('5')}]

parsed_item_list = {}

for item in items:
    assetId = int(item.get('AssetID'))
    rating = int(item.get('Rating'))
    if assetId not in parsed_item_list:
        parsed_item_list[assetId] = []
    parsed_item_list[assetId].append(rating)

print(parsed_item_list.get(0)[0]) # 3
print(parsed_item_list.get(0)[1]) # 5


问:
htaccess problem
I given htaccess like this

```<code>Options +FollowSymlinks
RewriteEngine On

RewriteBase /xxx/folder/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .  /xxx/folder/index.php [L]

RewriteRule  ^(.*)$ index.php?page=$1 [L]
</code>```

but giving the url like this
http://domain.com/faq

I get the page variable as index.php. I want to get  faq in $_GET['page'].How can i get this?

答:
Remove

```<code>RewriteBase /xxx/folder/
</code>```

Modify

```<code>RewriteRule  ^(.*)$ index.php?page=$1 [L]
</code>```

to

```<code>RewriteRule  ^(.*)$ xxx/folder/index.php?page=$1 [L]
</code>```

Title: htaccess problem

Body:
I given htaccess like this

Options +FollowSymlinks
RewriteEngine On

RewriteBase /xxx/folder/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .  /xxx/folder/index.php [L]

RewriteRule  ^(.*)$ index.php?page=$1 [L]

but giving the url like this
http://domain.com/faq

I get the page variable as index.php. I want to get  faq in $_GET['page'].How can i get this?

Body:
Remove

RewriteBase /xxx/folder/

Modify

RewriteRule  ^(.*)$ index.php?page=$1 [L]

to

RewriteRule  ^(.*)$ xxx/folder/index.php?page=$1 [L]


问:
Woocommerce: Only show related products from same subcategory
Related products is a section that pulls other products from your store that share the same tags or categories as the current product.

src: Woocommerce Docs

Lets say I sell tables (and other items) in my store. Tables is a category. I have 3 subcategorys that go with the table category: Small, Medium and Large.

What I want: when you click on a small table. The related products should only show small tables.
What it does: When you click on a small table. The related products shows a table from whatever size.

Does anyone know how I can change it to the way I want?

答:
Update for Woocommerce 3.9.0

Slight modification to the excellent answer given by @alejandro-restrepo - this version also excludes the current product from the related products query, and is modified from the Woocommerce 3.9.0 template.

Copy this code into [your-theme]/woocommerce/single-product/related.php

<?php
/**
 * Related Products
 *
 * This template can be overridden by copying it to yourtheme/woocommerce/single-product/related.php.
 *
 * HOWEVER, on occasion WooCommerce will need to update template files and you
 * (the theme developer) will need to copy the new files to your theme to
 * maintain compatibility. We try to do this as little as possible, but it does
 * happen. When this occurs the version of the template file will be bumped and
 * the readme will list any important changes.
 *
 * @see         https://docs.woocommerce.com/document/template-structure/
 * @author      WooThemes
 * @package     WooCommerce/Templates
 * @version     3.9.0
 */

if ( ! defined( 'ABSPATH' ) ) {
  exit;
}

global $product, $woocommerce_loop;

if ( empty( $product ) || ! $product->exists() ) {
  return;
}

if ( ! $related = $product->get_related( $posts_per_page ) ) {
  return;
}

// Get ID of current product, to exclude it from the related products query
$current_product_id = $product->get_id();

$cats_array = array(0);

// get categories
$terms = wp_get_post_terms( $product->get_id(), 'product_cat' );

// select only the category which doesn't have any children
foreach ( $terms as $term ) {
  $children = get_term_children( $term->term_id, 'product_cat' );
  if ( !sizeof( $children ) )
  $cats_array[] = $term->term_id;
}

$args = apply_filters( 'woocommerce_related_products_args', array(
  'post_type' => 'product',
  'post__not_in' => array( $current_product_id ),   // exclude current product
  'ignore_sticky_posts' => 1,
  'no_found_rows' => 1,
  'posts_per_page' => $posts_per_page,
  'orderby' => $orderby,
  'tax_query' => array(
    array(
        'taxonomy' => 'product_cat',
        'field' => 'id',
        'terms' => $cats_array
    ),
  )
));

$products                    = new WP_Query( $args );
$woocommerce_loop['name']    = 'related';
$woocommerce_loop['columns'] = apply_filters( 'woocommerce_related_products_columns', $columns );

if ( $products->have_posts() ) : ?>

    <?php
    $heading = apply_filters( 'woocommerce_product_related_products_heading', __( 'Related products', 'woocommerce' ) );

    if ( $heading ) :
    ?>

<?php echo esc_html( $heading ); ?>

    <?php endif; ?>

    <?php woocommerce_product_loop_start(); ?>

      <?php while ( $products->have_posts() ) : $products->the_post(); ?>

        <?php wc_get_template_part( 'content', 'product' ); ?>

      <?php endwhile; // end of the loop. ?>

    <?php woocommerce_product_loop_end(); ?>

<?php endif;

wp_reset_postdata();
```

Body:
Update for Woocommerce 3.9.0

Slight modification to the excellent answer given by @alejandro-restrepo - this version also excludes the current product from the related products query, and is modified from the Woocommerce 3.9.0 template.

Copy this code into [your-theme]/woocommerce/single-product/related.php

<?php
/**
 * Related Products
 *
 * This template can be overridden by copying it to yourtheme/woocommerce/single-product/related.php.
 *
 * HOWEVER, on occasion WooCommerce will need to update template files and you
 * (the theme developer) will need to copy the new files to your theme to
 * maintain compatibility. We try to do this as little as possible, but it does
 * happen. When this occurs the version of the template file will be bumped and
 * the readme will list any important changes.
 *
 * @see         https://docs.woocommerce.com/document/template-structure/
 * @author      WooThemes
 * @package     WooCommerce/Templates
 * @version     3.9.0
 */

if ( ! defined( 'ABSPATH' ) ) {
  exit;
}

global $product, $woocommerce_loop;

if ( empty( $product ) || ! $product->exists() ) {
  return;
}

if ( ! $related = $product->get_related( $posts_per_page ) ) {
  return;
}

// Get ID of current product, to exclude it from the related products query
$current_product_id = $product->get_id();

$cats_array = array(0);

// get categories
$terms = wp_get_post_terms( $product->get_id(), 'product_cat' );

// select only the category which doesn't have any children
foreach ( $terms as $term ) {
  $children = get_term_children( $term->term_id, 'product_cat' );
  if ( !sizeof( $children ) )
  $cats_array[] = $term->term_id;
}

$args = apply_filters( 'woocommerce_related_products_args', array(
  'post_type' => 'product',
  'post__not_in' => array( $current_product_id ),   // exclude current product
  'ignore_sticky_posts' => 1,
  'no_found_rows' => 1,
  'posts_per_page' => $posts_per_page,
  'orderby' => $orderby,
  'tax_query' => array(
    array(
        'taxonomy' => 'product_cat',
        'field' => 'id',
        'terms' => $cats_array
    ),
  )
));

$products                    = new WP_Query( $args );
$woocommerce_loop['name']    = 'related';
$woocommerce_loop['columns'] = apply_filters( 'woocommerce_related_products_columns', $columns );

if ( $products->have_posts() ) : ?>

  <section class="related products">

    <?php
    $heading = apply_filters( 'woocommerce_product_related_products_heading', __( 'Related products', 'woocommerce' ) );

    if ( $heading ) :
    ?>
      <h2><?php echo esc_html( $heading ); ?></h2>
    <?php endif; ?>

    <?php woocommerce_product_loop_start(); ?>

      <?php while ( $products->have_posts() ) : $products->the_post(); ?>

        <?php wc_get_template_part( 'content', 'product' ); ?>

      <?php endwhile; // end of the loop. ?>

    <?php woocommerce_product_loop_end(); ?>

  </section>

<?php endif;

wp_reset_postdata();


问:
Next js routing triggers useEffect
I'm trying to fetch data inside useEffect using axios but it fetches the data everytime I change the page. Is there a way to not trigger useEffect when changing the page? I tried to use shawllow push but it didn't work. I can't fetch on server side because I use next/router inside axios interceptor. </p>

```<code>   import { useRouter } from 'next/router';
   const router = useRouter();
   router.push('/', '/', { shallow: true })
</code>```

<p>With the above code, it will trigger useEffect when switching routes. </p>

```<code>  useEffect(() => {
    fetch.get('/endpoint').then(response => {
     // do stuff
    });
  }, []);
</code>```

答:
Shallow-routing only works for same page. See this.

If you stick to shallow-routing, you have to aggregate the pages into one page with dynamic-routes.

So I think it'd be better to use some cache strategy within useEffect.

Title: Next js routing triggers useEffect

Body:
I'm trying to fetch data inside useEffect using axios but it fetches the data everytime I change the page. Is there a way to not trigger useEffect when changing the page? I tried to use shawllow push but it didn't work. I can't fetch on server side because I use next/router inside axios interceptor.

   import { useRouter } from 'next/router';
   const router = useRouter();
   router.push('/', '/', { shallow: true })

With the above code, it will trigger useEffect when switching routes.

  useEffect(() => {
    fetch.get('/endpoint').then(response => {
     // do stuff
    });
  }, []);


问:
TimeFormat always from specific timezone
I have problem with date format I create App where I cant format time from current locale but always from specific locale UTC+1 or specific state, but I dont know how.

```<code>SimpleDateFormat("d.M.yyyy  HH:mm", Locale.getDefault()).format(Date(date))
</code>```

i need set locale or timezone like constant which not depend on physical position or phone settings.

I have data always in UTC-0 but I need transform it to UTC+1 (or other) and show to users.

Thanks for any help

For time sync I use TrueTime library

答:
Here is a java.time example that uses a ZonedDateTime created from a moment in time, that is an Instant in the mentioned package:

```<code>public static void main(String[] args) {
    // get a representation of a moment in time (not a specific date or time)
    Instant now = Instant.now();
    // then use that in order to represent it in a specific zone using an offset of -1 hour
    ZonedDateTime utcZdt = ZonedDateTime.ofInstant(now, ZoneOffset.ofHours(-1));
    // and use it again in order to have another one defined by a specific time zone
    ZonedDateTime laZdt = ZonedDateTime.ofInstant(now, ZoneId.of("America/Los_Angeles"));

    // and print the representation as String
    System.out.println(utcZdt.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
    System.out.println(laZdt.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
}
</code>```

The output is

2020-02-18T14:31:21.714-01:00
2020-02-18T07:31:21.714-08:00[America/Los_Angeles]
```

You can alternatively use an OffsetDateTime of the same package.

The key is to use an Instant, derived from epoch millis. Those millisecond values are moments in time, too, independent from zones or offsets.

You are coding an Android app, so you might have to use the ThreeTenABP, a backport of nearly the entire java.time functionality for API levels below Android 26.

I think that, nowadays, using java.time or a backport of it is the least troublesome and most straight-forward way to solve tasks like yours.

Body:
I have problem with date format I create App where I cant format time from current locale but always from specific locale UTC+1 or specific state, but I dont know how.

SimpleDateFormat("d.M.yyyy  HH:mm", Locale.getDefault()).format(Date(date))

i need set locale or timezone like constant which not depend on physical position or phone settings.

I have data always in UTC-0 but I need transform it to UTC+1 (or other) and show to users.

Thanks for any help

For time sync I use TrueTime library

Body:
Here is a java.time example that uses a ZonedDateTime created from a moment in time, that is an Instant in the mentioned package:

public static void main(String[] args) {
    // get a representation of a moment in time (not a specific date or time)
    Instant now = Instant.now();
    // then use that in order to represent it in a specific zone using an offset of -1 hour
    ZonedDateTime utcZdt = ZonedDateTime.ofInstant(now, ZoneOffset.ofHours(-1));
    // and use it again in order to have another one defined by a specific time zone
    ZonedDateTime laZdt = ZonedDateTime.ofInstant(now, ZoneId.of("America/Los_Angeles"));

    // and print the representation as String
    System.out.println(utcZdt.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
    System.out.println(laZdt.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
}

The output is

2020-02-18T14:31:21.714-01:00
2020-02-18T07:31:21.714-08:00[America/Los_Angeles]

You can alternatively use an OffsetDateTime of the same package.

The key is to use an Instant, derived from epoch millis. Those millisecond values are moments in time, too, independent from zones or offsets.

You are coding an Android app, so you might have to use the ThreeTenABP, a backport of nearly the entire java.time functionality for API levels below Android 26.

I think that, nowadays, using java.time or a backport of it is the least troublesome and most straight-forward way to solve tasks like yours.


问:
How to filter myself out of Google Analytics with a dynamic IP address?
Does anyone know how to setup Google Analytics to filter yourself out if you're visiting the site from a dynamic IP address?  I don't want to include myself in my stats from home use where I have a dynamic IP address via Verizon FiOS.</p>

答:
Google currently has a browser add-on that will block any visits of yours from showing up in any Analytics. http://tools.google.com/dlpage/gaoptout

Pluses and minuses of this opt-out versus filters are discussed in this blog post.

OwnerDisplayName: magenta

ContentLicense: CC BY-SA 2.5


问:
How to define a function with a parameter in it in Octave?
I am trying to define a function with a predefined variable, and Octave says that the variable was not defined. I am trying to run the following code in Octave,

q = 5;
function w = tointegrate(x)
  w = 2 * q * sin(x);
endfunction
[ans, ier, nfun, err] = quad("tointegrate", -10*q, 10*q);
ans
```

<p>Octave gives the error</p>

<blockquote>
```error: 'q' undefined near line 3 column 10
error: quad: evaluation of user-supplied function failed
```

How to fix this error?

答:
You can solve this by having q be a parameter to the function, then creating an anonymous function to call quad, like so:

function w = tointegrate(x, q)
  w = 2 * q * sin(x);
endfunction

q = 5;
[ans, ier, nfun, err] = quad(@(x)tointegrate(x,q), -10*q, 10*q);
ans
```

Body:
I am trying to define a function with a predefined variable, and Octave says that the variable was not defined. I am trying to run the following code in Octave,

q = 5;
function w = tointegrate(x)
  w = 2 * q * sin(x);
endfunction
[ans, ier, nfun, err] = quad("tointegrate", -10*q, 10*q);
ans

Octave gives the error

error: 'q' undefined near line 3 column 10
error: quad: evaluation of user-supplied function failed

How to fix this error?


问:
How to replace values in selected rows columns with an array in dataframe?
I have a df

```<code>df = pd.DataFrame(data={'A': [1,2,3,4,5,6,7,8],
                       'B': [10,20,30,40,50,60,70,80]})
    A   B
0   1   10
1   2   20
2   3   30
3   4   40
4   5   50
5   6   60
6   7   70
7   8   80
</code>```

which I selected a few rows from.
Then I have a dictionary containig values that I should insert in B column
if key matches with value in A column of df

```<code>my_dict = {2: 39622884,
           4: 82709546,
           5: 28166511,
           7: 89465652}
</code>```

When I use the following assignment

```<code>df.loc[df['A'].isin(my_dict.keys())]['B'] = list(my_dict.values())
</code>```

I get the error:
ValueError: Length of values does not match length of index

The desirable output is

```<code>    A   B
0   1   10
1   2   39622884
2   3   30
3   4   82709546
4   5   50
5   6   28166511
6   7   89465652
7   8   80
</code>```

What is the correct way to implement this procedure?

Body:
I have a df

df = pd.DataFrame(data={'A': [1,2,3,4,5,6,7,8],
                       'B': [10,20,30,40,50,60,70,80]})
    A   B
0   1   10
1   2   20
2   3   30
3   4   40
4   5   50
5   6   60
6   7   70
7   8   80

which I selected a few rows from.
Then I have a dictionary containig values that I should insert in B column
if key matches with value in A column of df

my_dict = {2: 39622884,
           4: 82709546,
           5: 28166511,
           7: 89465652}

When I use the following assignment

df.loc[df['A'].isin(my_dict.keys())]['B'] = list(my_dict.values())

I get the error:
ValueError: Length of values does not match length of index

The desirable output is

    A   B
0   1   10
1   2   39622884
2   3   30
3   4   82709546
4   5   50
5   6   28166511
6   7   89465652
7   8   80

What is the correct way to implement this procedure?

Body:
You can make do with map and fillna:

df['B'] = df['A'].map(my_dict).fillna(df['B'])

Output:

   A           B
0  1        10.0
1  2  39622884.0
2  3        30.0
3  4  82709546.0
4  5  28166511.0
5  6        60.0
6  7  89465652.0
7  8        80.0


问:
Testing functions with properties using Jest and Sinon
am trying to write tests to test streams on my app, dealing with fs library with its createWriteStream function, so the stub i created is as follows:

```<code>writeStreamStub = sinon.stub()
onceStreamEventStub = sinon.stub()
endStreamStub = sinon.stub()
onStreamStub = sinon.stub()

createStreamStub = sinon.stub(fs, 'createWriteStream').returns({
  write: writeStreamStub,
  once: onceStreamEventStub,
  end: endStreamStub,
  on: onStreamStub
})
</code>```

So now I can test for whether the functions are called and the returned functions are also called. But I am using the --coverage flag and the code of the callbacks of the returned functions is not covered, the write method is called inside a process.nextTick and I have no idea how to go about this. Is it possible to cover the whole code and the code inside the callbacks, and if so, how do I go about it. Thanks in advance.

N.B. The variables are globaly declared

答:
If there's no cogent reason to use both sinon and jest, I'd recommend just using one library. If you decide to go with jest, here's a simple example. Assume you have a class like

```<code>const fs = require('fs');

module.exports = class FileWriter {
  constructor() {
    this.writer = fs.createWriteStream('./testfile.txt');
  }

  writeFile() {
    process.nextTick(() => {
      this.writeContent('hello world');
    });
  }

  writeContent(content) {
    this.writer.write(content);
    this.writer.end();
  }

};
</code>```

and in your unit-test you want to mock the behaviour of all the used fs-functions (createWriteStream, writer, end in this case) and just check if they are called with the correct arguments. You could do this with something like this:

```<code>const fs = require('fs');
const FileWriter = require('./FileWriter');
// use this to have mocks for all of fs' functions (you could use jest.fn() instead as well)
jest.mock('fs');
describe('FileWriter', () => {
  it('should write file with correct args', async () => {
    const writeStub = jest.fn().mockReturnValue(true);
    const endStub = jest.fn().mockReturnValue(true);
    const writeStreamStub = fs.createWriteStream.mockReturnValue({
      write: writeStub,
      end: endStub,
    });

    const fileWriter = new FileWriter();
    fileWriter.writeFile();
    await waitForNextTick();
    expect(writeStreamStub).toBeCalledWith('./testfile.txt');
    expect(writeStub).toBeCalledWith('hello world');
    expect(endStub).toHaveBeenCalled();
  });
});

function waitForNextTick() {
  return new Promise(resolve => process.nextTick(resolve));
}
</code>```

Body:
am trying to write tests to test streams on my app, dealing with fs library with its createWriteStream function, so the stub i created is as follows:

writeStreamStub = sinon.stub()
onceStreamEventStub = sinon.stub()
endStreamStub = sinon.stub()
onStreamStub = sinon.stub()

createStreamStub = sinon.stub(fs, 'createWriteStream').returns({
  write: writeStreamStub,
  once: onceStreamEventStub,
  end: endStreamStub,
  on: onStreamStub
})

So now I can test for whether the functions are called and the returned functions are also called. But I am using the --coverage flag and the code of the callbacks of the returned functions is not covered, the write method is called inside a process.nextTick and I have no idea how to go about this. Is it possible to cover the whole code and the code inside the callbacks, and if so, how do I go about it. Thanks in advance.

N.B. The variables are globaly declared

Body:
If there's no cogent reason to use both sinon and jest, I'd recommend just using one library. If you decide to go with jest, here's a simple example. Assume you have a class like

const fs = require('fs');

module.exports = class FileWriter {
  constructor() {
    this.writer = fs.createWriteStream('./testfile.txt');
  }

  writeFile() {
    process.nextTick(() => {
      this.writeContent('hello world');
    });
  }

  writeContent(content) {
    this.writer.write(content);
    this.writer.end();
  }

};

and in your unit-test you want to mock the behaviour of all the used fs-functions (createWriteStream, writer, end in this case) and just check if they are called with the correct arguments. You could do this with something like this:

const fs = require('fs');
const FileWriter = require('./FileWriter');
// use this to have mocks for all of fs' functions (you could use jest.fn() instead as well)
jest.mock('fs');
describe('FileWriter', () => {
  it('should write file with correct args', async () => {
    const writeStub = jest.fn().mockReturnValue(true);
    const endStub = jest.fn().mockReturnValue(true);
    const writeStreamStub = fs.createWriteStream.mockReturnValue({
      write: writeStub,
      end: endStub,
    });

    const fileWriter = new FileWriter();
    fileWriter.writeFile();
    await waitForNextTick();
    expect(writeStreamStub).toBeCalledWith('./testfile.txt');
    expect(writeStub).toBeCalledWith('hello world');
    expect(endStub).toHaveBeenCalled();
  });
});

function waitForNextTick() {
  return new Promise(resolve => process.nextTick(resolve));
}


问:
Quartiles and other parameters in groupby on multiple keys in pandas python
df columns are as below:

```<code>  Key1   Key2   Val1
</code>```

Output needed
I want groupby output where Val1 column has values clubbed together with groupby in python on keys Key1 and Key2.

Output expected: df2  [groupby on key1 and key2]

```<code>Key1 Key2 Val1  Count Sum Q1  Q2  Q3
</code>```

答:
```<code>df2 = df.groupby(['Key1','Key2'])['Val1']
         .agg([('Count','count'),
               ('Sum','sum'),
               ('Q1', lambda x: x.quantile(0.25)),
               ('Q2', lambda x: x.quantile(0.5)),
               ('Q3', lambda x: x.quantile(0.75))])
</code>```

Body:
df columns are as below:

  Key1   Key2   Val1

Output needed
I want groupby output where Val1 column has values clubbed together with groupby in python on keys Key1 and Key2.

Output expected: df2  [groupby on key1 and key2]

Key1 Key2 Val1  Count Sum Q1  Q2  Q3


问:
Communicating between Activities and Fragments when using Navigation Architecture Component
I want to let the host Activity know when something happens in a Fragment. Traditionally, I would have an interface with a callback that the Fragment can call, but now we are ofc using the navigation architecture component.

Is there a way to pass a reference to the host activity down to the fragments or how would I otherwise solve the "Communication between activities and fragments" situation?

Thanks!

答: you can have a shared ViewModel between your activity and all of your fragments. and use liveData in that viewModel. so when something happens in the fragments you change the liveData and you observe the liveData in the activity</p>


问:
how to add formatter tooltip in echart for multiple values for pie diagram
I am using echart pie diagram but I want to show multiple records in tooltip.

```<code>option = {
    tooltip: {
        trigger: 'item',
        formatter: '{a} <br/>{b} : {c} ({d}%), <br/>{name1} : {value1} '
    },
    legend: {
        orient: 'vertical',
        left: 'left',
        data: ['aa', 'bb', 'cc', 'dd', 'ee']
    },
    series: [
        {
            name: 'text name',
            type: 'pie',
            radius: '55%',
            center: ['50%', '60%'],
            data: [
                {value: 335, name: 'aa',value1: 335, name1: 'xx'},
                {value: 310, name: 'bb',value1: 335, name1: 'yy'},
                {value: 234, name: 'cc',value1: 335, name1: 'zz'},
                {value: 135, name: 'dd',value1: 335, name1: 'ww'},
                {value: 1548, name: 'ee',value1: 335, name1: 'vv'}
            ],
        }
    ]
};
</code>```

I have tried with this formatter: '{a}
{b} : {c} ({d}%),
{e} : {f} ({g}%)' and
'<%=name%>:<%= value %><%\n%><%=name1%>:<%= value1%><%\n%><%=name2%>:<%= value2 %>' this
 link :https://echarts.apache.org/examples/en/editor.html?c=pie-simple

答:
If you want to customize the tooltip then you can use a callback function for formatter property and access all the related data. I have created a demo for you, please let me know if you face any issue.

// 基于准备好的dom，初始化echarts实例
var myChart = echarts.init(document.getElementById('main'));

option = {
  tooltip: {
    trigger: 'item',
    formatter: function (params) {

      return `${params.seriesName}

              ${params.name}: ${params.data.value} (${params.percent}%)

              ${params.data.name1}: ${params.data.value1}`;
    }
  },
  legend: {
    orient: 'vertical',
    left: 'left',
    data: ['aa', 'bb', 'cc', 'dd', 'ee']
  },
  series: [{
    name: 'text name',
    type: 'pie',
    radius: '55%',
    center: ['50%', '60%'],
    data: [{
        value: 335,
        name: 'aa',
        value1: 335,
        name1: 'xx'
      },
      {
        value: 310,
        name: 'bb',
        value1: 335,
        name1: 'yy'
      },
      {
        value: 234,
        name: 'cc',
        value1: 335,
        name1: 'zz'
      },
      {
        value: 135,
        name: 'dd',
        value1: 335,
        name1: 'ww'
      },
      {
        value: 1548,
        name: 'ee',
        value1: 335,
        name1: 'vv'
      }
    ],
  }]
};

// use configuration item and data specified to show chart
myChart.setOption(option);```
<pre class="snippet-code-html lang-html prettyprint-override"><code><script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/3.7.2/echarts.min.js"></script>
<div id="main" style="width: 600px;height:400px;"></div></code>```

Body:
I am using echart pie diagram but I want to show multiple records in tooltip.

option = {
    tooltip: {
        trigger: 'item',
        formatter: '{a}
{b} : {c} ({d}%),
{name1} : {value1} '
    },
    legend: {
        orient: 'vertical',
        left: 'left',
        data: ['aa', 'bb', 'cc', 'dd', 'ee']
    },
    series: [
        {
            name: 'text name',
            type: 'pie',
            radius: '55%',
            center: ['50%', '60%'],
            data: [
                {value: 335, name: 'aa',value1: 335, name1: 'xx'},
                {value: 310, name: 'bb',value1: 335, name1: 'yy'},
                {value: 234, name: 'cc',value1: 335, name1: 'zz'},
                {value: 135, name: 'dd',value1: 335, name1: 'ww'},
                {value: 1548, name: 'ee',value1: 335, name1: 'vv'}
            ],
        }
    ]
};

I have tried with this formatter: '{a}
{b} : {c} ({d}%),
{e} : {f} ({g}%)' and
'<%=name%>:<%= value %><%\n%><%=name1%>:<%= value1%><%\n%><%=name2%>:<%= value2 %>' this
 link :https://echarts.apache.org/examples/en/editor.html?c=pie-simple

Body:
If you want to customize the tooltip then you can use a callback function for formatter property and access all the related data. I have created a demo for you, please let me know if you face any issue.

// 基于准备好的dom，初始化echarts实例
var myChart = echarts.init(document.getElementById('main'));

option = {
  tooltip: {
    trigger: 'item',
    formatter: function (params) {

      return `${params.seriesName}<br />
              ${params.name}: ${params.data.value} (${params.percent}%)<br />
              ${params.data.name1}: ${params.data.value1}`;
    }
  },
  legend: {
    orient: 'vertical',
    left: 'left',
    data: ['aa', 'bb', 'cc', 'dd', 'ee']
  },
  series: [{
    name: 'text name',
    type: 'pie',
    radius: '55%',
    center: ['50%', '60%'],
    data: [{
        value: 335,
        name: 'aa',
        value1: 335,
        name1: 'xx'
      },
      {
        value: 310,
        name: 'bb',
        value1: 335,
        name1: 'yy'
      },
      {
        value: 234,
        name: 'cc',
        value1: 335,
        name1: 'zz'
      },
      {
        value: 135,
        name: 'dd',
        value1: 335,
        name1: 'ww'
      },
      {
        value: 1548,
        name: 'ee',
        value1: 335,
        name1: 'vv'
      }
    ],
  }]
};

// use configuration item and data specified to show chart
myChart.setOption(option);

<script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/3.7.2/echarts.min.js"></script>
<div id="main" style="width: 600px;height:400px;"></div>


问:
How to save a string temporary variable in assembly x86-64
Im new to assembly and I've to write the memmove function in assembly x86-64, and it said :

The memmove() function copies n bytes from memory area src to memory area dest. The memory areas may overlap: copying takes place as though the bytes in src are first copied into a temporary array that does not overlap src or dest, and the bytes are then copied from the temporary array to dest.

Nevertheless, I don't find a way to save a temporary string in assembly, and that's why I am posting this.

I tried to put in rax register, but I got a segmentation fault :

```<code>mov r8b, byte [rsi + rcx] ; rsi is source string
mov byte [rax + rcx], r8b
</code>```

By the way, I'm using nasm -f elf64 memmove.asm on my build

Thank you.

答:
Machine instruction MOVSB
will be your friend in copying memory areas. It copies one byte from memory addressed by RSI
to the memory addressed by RDI and then modifies both registers to the next element (byte).

```<code>SECTION .data
Memory   DB '0123456789'
Src1st   EQU Memory+0
SrcLast  EQU Memory+4
Dest1st  EQU Memory+3
DestLast EQU Memory+7
SECTION .text
   LEA RSI,[Src1st]
   LEA RDI,[Dest1st]
   CLD
</code>```

We can visualize memory layout before MOVSB this way

```<code>  RSI   RDI
   |     |
   0 1 2 3 4 5 6 7 8 9
   _________        Src
         _________  Dest
</code>```

After MOVSB

```<code>    RSI   RDI
     |     |
   0 1 2 0 4 5 6 7 8 9
</code>```

With instruction prefix REP it is repeated RCX times.
After

```<code>MOV RCX,DestLast-Dest1st+1
REP MOVSB
                RSI   RDI
                 |     |
       0 1 2 0 1 2 0 1 8 9
</code>```

This doesn't work as expected when Src and Dest areas overlap - instead of 0120123489 we've got 0120120189.
When the destination field is above the source (RDI>RSI), we must copy backward (set Direction Flag)
and start with registers pointing at the end of fields.

```<code>   LEA RSI,[SrcLast]
   LEA RDI,[DestLast]
   MOV RCX,DestLast-Dest1st+1

          RSI   RDI
           |     |
   0 1 2 3 4 5 6 7 8 9
</code>```

After

```<code>   STD
   REP MOVSB

RSI   RDI
 |     |
   0 1 2 0 1 2 3 4 8 9
</code>```

Source field is copied verbatim to the destination without temporary array, not wasting memory and clocks. The direction flag should be reset to its default state after backward copy, which is expected by interface of most operational systems and library functions.

Body:
Im new to assembly and I've to write the memmove function in assembly x86-64, and it said :

The memmove() function copies n bytes from memory area src to memory area dest. The memory areas may overlap: copying takes place as though the bytes in src are first copied into a temporary array that does not overlap src or dest, and the bytes are then copied from the temporary array to dest.

Nevertheless, I don't find a way to save a temporary string in assembly, and that's why I am posting this.

I tried to put in rax register, but I got a segmentation fault :

mov r8b, byte [rsi + rcx] ; rsi is source string
mov byte [rax + rcx], r8b

By the way, I'm using nasm -f elf64 memmove.asm on my build

Thank you.

Body:
Machine instruction MOVSB
will be your friend in copying memory areas. It copies one byte from memory addressed by RSI
to the memory addressed by RDI and then modifies both registers to the next element (byte).

SECTION .data
Memory   DB '0123456789'
Src1st   EQU Memory+0
SrcLast  EQU Memory+4
Dest1st  EQU Memory+3
DestLast EQU Memory+7
SECTION .text
   LEA RSI,[Src1st]
   LEA RDI,[Dest1st]
   CLD

We can visualize memory layout before MOVSB this way

  RSI   RDI
   |     |
   0 1 2 3 4 5 6 7 8 9
   _________        Src
         _________  Dest

After MOVSB

    RSI   RDI
     |     |
   0 1 2 0 4 5 6 7 8 9

With instruction prefix REP it is repeated RCX times.
After

MOV RCX,DestLast-Dest1st+1
REP MOVSB
                RSI   RDI
                 |     |
       0 1 2 0 1 2 0 1 8 9

This doesn't work as expected when Src and Dest areas overlap - instead of 0120123489 we've got 0120120189.
When the destination field is above the source (RDI>RSI), we must copy backward (set Direction Flag)
and start with registers pointing at the end of fields.

   LEA RSI,[SrcLast]
   LEA RDI,[DestLast]
   MOV RCX,DestLast-Dest1st+1

          RSI   RDI
           |     |
   0 1 2 3 4 5 6 7 8 9

After

   STD
   REP MOVSB

RSI   RDI
 |     |
   0 1 2 0 1 2 3 4 8 9

Source field is copied verbatim to the destination without temporary array, not wasting memory and clocks. The direction flag should be reset to its default state after backward copy, which is expected by interface of most operational systems and library functions.


问:
PHP trouble json_decoding multi level json array
I am trying to parse json from Amazon SNS using PHP and json_decode.

I am storing the json from Amazon in a mysql database, and then looping through the rows to hopefully display a table of all notifications.

This is the original json that comes in:

```<code>{
"Type": "Notification",
"MessageId": "4ecca6d5-3095-5d5c-a0f0-f013dc59f33e",
"TopicArn": "arn:aws:sns:eu-west-1:826492718737:Email_Notifications",
"Message": "{\"notificationType\":\"Delivery\",\"mail\":{\"timestamp\":\"2020-02-19T07:58:03.541Z\",\"source\":\"do-not-reply@supplyplus.org.uk\",\"sourceArn\":\"arn:aws:ses:eu-west-1:826492718737:identity/do-not-reply@supplyplus.org.uk\",\"sourceIp\":\"82.68.110.206\",\"sendingAccountId\":\"826492718737\",\"messageId\":\"010201705c743115-5bc7fc12-f36d-425a-8ff8-14ea0acf073b-000000\",\"destination\":[\"edward.hall@setsquaresolutions.com\"]},\"delivery\":{\"timestamp\":\"2020-02-19T07:58:04.226Z\",\"processingTimeMillis\":685,\"recipients\":[\"edward.hall@setsquaresolutions.com\"],\"smtpResponse\":\"250 2.0.0 OK  1582099084 z21si661666ejr.129 - gsmtp\",\"remoteMtaIp\":\"209.85.202.27\",\"reportingMTA\":\"a4-7.smtp-out.eu-west-1.amazonses.com\"}}",
"Timestamp": "2020-02-19T07:58:04.286Z",
"SignatureVersion": "1",
"Signature": "XjCUN+iogrinljvfc32wG55UUT1WUVhhIpXYPZtW9IcBiJfBnlQETy2LNlLPnGjtqcKKuV8IKQbC06DIW3EeiKGzfxeQE8OthJJOEGexcA1qr6EbMPLalhDRSmmoUC8a6vY4d3Gn/R98lzaij5UUbT9y4Oesuq8NFR98m8WpOZqMwBdjsRRhZuN676c/or9x6ibU1kWExXKxw/Cw77hhkT5Hd52gNsg2nla+V6oVWXfn/jCmUWByrJRFdxe1nUm+WbcNT4nCkqKxUBT/NTA5RkD72Mr+X/470WNXBJZ6OP/4tbby3bcn7BxzZBA780c2OBtRlseD2MvKJGE8qss2og==",
"SigningCertURL": "https://sns.eu-west-1.amazonaws.com/SimpleNotificationService-a86cb10b4e1f29c941702d737128f7b6.pem",
"UnsubscribeURL": "https://sns.eu-west-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:eu-west-1:826492718737:Email_Notifications:b584a2d6-c9e3-4401-a029-7b6fd4603274"
</code>```

}

The json after it has been inserted into the database looks like this:

```<code>{
  "Type" : "Notification",
  "MessageId" : "3ce843a7-13c2-54f8-a445-1561121fd162",
  "TopicArn" : "arn:aws:sns:eu-west-1:826492718737:Email_Notifications",
  "Message" : "{"notificationType":"Delivery","mail":{"timestamp":"2020-02-18T15:15:40.879Z","source":"do-not-reply@example.com","sourceArn":"arn:aws:ses:eu-west-1:826492718737:identity/do-not-reply@example.com","sourceIp":"12.34.56.78","sendingAccountId":"826492718737","messageId":"0102017058de7ccf-55c4a34d-fcd1-449c-a82a-9946b316e551-000000","destination":["user@example.com"]},"delivery":{"timestamp":"2020-02-18T15:15:41.527Z","processingTimeMillis":648,"recipients":["user@example.com"],"smtpResponse":"250 2.0.0 OK  1582038941 p17si2420323wma.126 - gsmtp","remoteMtaIp":"12.34.56.78","reportingMTA":"a4-8.smtp-out.eu-west-1.amazonses.com"}}",
  "Timestamp" : "2020-02-18T15:15:41.574Z",
  "SignatureVersion" : "1",
  "Signature" : "UTzy1PLgzxyz7wczh/3ZrcKiT9MCFe7pcmeOLH3whZ6tRbq1B6pjv+cEjTFKR3RnH4D9CkDQq04vpTyj3ATwJ5ZSxVOuNmGEo1KuOjH8TveaB3PzQTpwQlsVg1fzW5wCmhND9dvDuXiTGc86Lvy4e9AlmGNHTrfbAa5fZIfFfP9PzEhHF8zcyIvZd//2Ni4hmAvx4MKtdlke/m2Uacn9bSF61pVD/QCZOsFkV7ovfqiRZZmdXOaFb8dTZeBlU98jJLvIwDk5C5lKG7Ru8V+Gs8g13iQyS3v7xI35lVQUo52U+srk5Ndc5AdR6C3COW2r12g7eWacypP+phU2vr8uTA==",
  "SigningCertURL" : "https://sns.eu-west-1.amazonaws.com/SimpleNotificationService-a86cb10b4e1f29c941702d737128f7b6.pem",
  "UnsubscribeURL" : "https://sns.eu-west-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:eu-west-1:826492718737:Email_Notifications:b584a2d6-c9e3-4401-a029-7b6fd4603274"
}
</code>```

When I try to convert this to a php array using:

```<code>var_dump(json_decode($json, true));
</code>```

It returns null, I have discovered that this only happens when I include the "Message" which includes sub-arrays. If I remove the "Message" part, then the php array returns correctly.

How can I correctly convert this json to a PHP associative array?

I am losing the backslashes after the json has been inserted into the database, if I can prevent that then this should work.

Edit:

I am inserting the json into the database like this, I have also tried json_encode and decode on the file_get_contents before inserting it:

```<code>$json = file_get_contents('php://input');

$mysqli->query("INSERT INTO `log` (json) VALUES('{$json}'));
</code>```

答:
You are saying you are "including" message part so I guess this is not the original JSON payload received from amazon?

Can you tell what do you mean by including the Message part?

when you get JSON response from SNS do the following:

```<code>$data = json_decode($postData, true);
$data['Message'] = json_decode($data['Message'], true);
</code>```

this will give you correct array structure. Depending on the string format you might need to unescape the field before decode. This is because Message contains another separate JSON message structure encoded as a string.

I sincerely doubt that above message dump contains all characters you receive in the post from SNS. SNS will send a valid JSON response, so I have to assume the actual rasponse has properly encoded json payload as a string in the Message field.

Body:
I am trying to parse json from Amazon SNS using PHP and json_decode.

I am storing the json from Amazon in a mysql database, and then looping through the rows to hopefully display a table of all notifications.

This is the original json that comes in:

{
"Type": "Notification",
"MessageId": "4ecca6d5-3095-5d5c-a0f0-f013dc59f33e",
"TopicArn": "arn:aws:sns:eu-west-1:826492718737:Email_Notifications",
"Message": "{\"notificationType\":\"Delivery\",\"mail\":{\"timestamp\":\"2020-02-19T07:58:03.541Z\",\"source\":\"do-not-reply@supplyplus.org.uk\",\"sourceArn\":\"arn:aws:ses:eu-west-1:826492718737:identity/do-not-reply@supplyplus.org.uk\",\"sourceIp\":\"82.68.110.206\",\"sendingAccountId\":\"826492718737\",\"messageId\":\"010201705c743115-5bc7fc12-f36d-425a-8ff8-14ea0acf073b-000000\",\"destination\":[\"edward.hall@setsquaresolutions.com\"]},\"delivery\":{\"timestamp\":\"2020-02-19T07:58:04.226Z\",\"processingTimeMillis\":685,\"recipients\":[\"edward.hall@setsquaresolutions.com\"],\"smtpResponse\":\"250 2.0.0 OK  1582099084 z21si661666ejr.129 - gsmtp\",\"remoteMtaIp\":\"209.85.202.27\",\"reportingMTA\":\"a4-7.smtp-out.eu-west-1.amazonses.com\"}}",
"Timestamp": "2020-02-19T07:58:04.286Z",
"SignatureVersion": "1",
"Signature": "XjCUN+iogrinljvfc32wG55UUT1WUVhhIpXYPZtW9IcBiJfBnlQETy2LNlLPnGjtqcKKuV8IKQbC06DIW3EeiKGzfxeQE8OthJJOEGexcA1qr6EbMPLalhDRSmmoUC8a6vY4d3Gn/R98lzaij5UUbT9y4Oesuq8NFR98m8WpOZqMwBdjsRRhZuN676c/or9x6ibU1kWExXKxw/Cw77hhkT5Hd52gNsg2nla+V6oVWXfn/jCmUWByrJRFdxe1nUm+WbcNT4nCkqKxUBT/NTA5RkD72Mr+X/470WNXBJZ6OP/4tbby3bcn7BxzZBA780c2OBtRlseD2MvKJGE8qss2og==",
"SigningCertURL": "https://sns.eu-west-1.amazonaws.com/SimpleNotificationService-a86cb10b4e1f29c941702d737128f7b6.pem",
"UnsubscribeURL": "https://sns.eu-west-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:eu-west-1:826492718737:Email_Notifications:b584a2d6-c9e3-4401-a029-7b6fd4603274"

}

The json after it has been inserted into the database looks like this:

{
  "Type" : "Notification",
  "MessageId" : "3ce843a7-13c2-54f8-a445-1561121fd162",
  "TopicArn" : "arn:aws:sns:eu-west-1:826492718737:Email_Notifications",
  "Message" : "{"notificationType":"Delivery","mail":{"timestamp":"2020-02-18T15:15:40.879Z","source":"do-not-reply@example.com","sourceArn":"arn:aws:ses:eu-west-1:826492718737:identity/do-not-reply@example.com","sourceIp":"12.34.56.78","sendingAccountId":"826492718737","messageId":"0102017058de7ccf-55c4a34d-fcd1-449c-a82a-9946b316e551-000000","destination":["user@example.com"]},"delivery":{"timestamp":"2020-02-18T15:15:41.527Z","processingTimeMillis":648,"recipients":["user@example.com"],"smtpResponse":"250 2.0.0 OK  1582038941 p17si2420323wma.126 - gsmtp","remoteMtaIp":"12.34.56.78","reportingMTA":"a4-8.smtp-out.eu-west-1.amazonses.com"}}",
  "Timestamp" : "2020-02-18T15:15:41.574Z",
  "SignatureVersion" : "1",
  "Signature" : "UTzy1PLgzxyz7wczh/3ZrcKiT9MCFe7pcmeOLH3whZ6tRbq1B6pjv+cEjTFKR3RnH4D9CkDQq04vpTyj3ATwJ5ZSxVOuNmGEo1KuOjH8TveaB3PzQTpwQlsVg1fzW5wCmhND9dvDuXiTGc86Lvy4e9AlmGNHTrfbAa5fZIfFfP9PzEhHF8zcyIvZd//2Ni4hmAvx4MKtdlke/m2Uacn9bSF61pVD/QCZOsFkV7ovfqiRZZmdXOaFb8dTZeBlU98jJLvIwDk5C5lKG7Ru8V+Gs8g13iQyS3v7xI35lVQUo52U+srk5Ndc5AdR6C3COW2r12g7eWacypP+phU2vr8uTA==",
  "SigningCertURL" : "https://sns.eu-west-1.amazonaws.com/SimpleNotificationService-a86cb10b4e1f29c941702d737128f7b6.pem",
  "UnsubscribeURL" : "https://sns.eu-west-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:eu-west-1:826492718737:Email_Notifications:b584a2d6-c9e3-4401-a029-7b6fd4603274"
}

When I try to convert this to a php array using:

var_dump(json_decode($json, true));

It returns null, I have discovered that this only happens when I include the "Message" which includes sub-arrays. If I remove the "Message" part, then the php array returns correctly.

How can I correctly convert this json to a PHP associative array?

I am losing the backslashes after the json has been inserted into the database, if I can prevent that then this should work.

Edit:

I am inserting the json into the database like this, I have also tried json_encode and decode on the file_get_contents before inserting it:

$json = file_get_contents('php://input');

$mysqli->query("INSERT INTO `log` (json) VALUES('{$json}'));

Body:
You are saying you are "including" message part so I guess this is not the original JSON payload received from amazon?

Can you tell what do you mean by including the Message part?

when you get JSON response from SNS do the following:

$data = json_decode($postData, true);
$data['Message'] = json_decode($data['Message'], true);

this will give you correct array structure. Depending on the string format you might need to unescape the field before decode. This is because Message contains another separate JSON message structure encoded as a string.

I sincerely doubt that above message dump contains all characters you receive in the post from SNS. SNS will send a valid JSON response, so I have to assume the actual rasponse has properly encoded json payload as a string in the Message field.


问:
Flutter Google Maps, Trying to create an already created platform view, view id: 0
For first time google maps flutter ,loads perfect but when hot restart it , it goes to platform exception

google_maps_flutter: ^0.5.21+15

Github [google_maps_flutter] Trying to create an already created platform view #45695

```<code>[ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: PlatformException(error, java.lang.IllegalStateException: Trying to create an already created platform view, view id: 0
</code>```

Flutter doctor -v

```<code>[✓] Flutter (Channel stable, v1.12.13+hotfix.5, on Linux, locale en_IN)
    • Flutter version 1.12.13+hotfix.5 at /home/asus/Documents/Flutter_SDK/flutter
    • Framework revision 27321ebbad (2 weeks ago), 2019-12-10 18:15:01 -0800
    • Engine revision 2994f7e1e6
    • Dart version 2.7.0

[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
    • Android SDK at /home/asus/Android/Sdk
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-29, build-tools 29.0.2
    • Java binary at: /snap/android-studio/81/android-studio/jre/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)
    • All Android licenses accepted.

[✓] Android Studio (version 3.5)
    • Android Studio at /snap/android-studio/81/android-studio
    • Flutter plugin version 42.1.1
    • Dart plugin version 191.8593
    • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)

[✓] Connected device (1 available)
    • vivo 1723 • 49269ad3 • android-arm64 • Android 9 (API 28)

• No issues found!
</code>```

答:
I also had the same issue and using flutter clean didn't solve it for me (flutter version 1.12.13+hotfix 8)

But then, adding a unique key to the widget (not to its state) solved the issue for me.

minimum working code sample to demonstrate this.

```<code>import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Map not crashing demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: LocationScreen(),
    );
  }
}

class LocationScreen extends StatefulWidget
{
  final Key _mapKey = UniqueKey();
  @override
  _LocationScreenState createState() => _LocationScreenState();
}

class _LocationScreenState extends State<LocationScreen>
{
  @override
  Widget build(BuildContext context)
  {
    return Scaffold(
      appBar: AppBar(title: const Text('Map not crashing demo')),
      body: TheMap(key:widget._mapKey)
    );
  }
}

class TheMap extends StatefulWidget
{
  ///key is required, otherwise map crashes on hot reload
  TheMap({ @required Key key})
  :
  super(key:key);

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<TheMap>
{
  GoogleMapController _mapController ;

  void _onMapCreated(GoogleMapController controller) {
    _mapController = controller;
  }
  @override
  Widget build(BuildContext context)
  {
    return Scaffold(
      //also this avoids it crashing/breaking when the keyboard is up
      resizeToAvoidBottomInset: false,
      body: GoogleMap(
          onMapCreated: _onMapCreated,
          initialCameraPosition: CameraPosition(
            target: const LatLng(30.0925973,31.3219982),
            zoom: 11.0,
          ),
        )
    );
  }
}
</code>```

Body:
For first time google maps flutter ,loads perfect but when hot restart it , it goes to platform exception

google_maps_flutter: ^0.5.21+15

Github [google_maps_flutter] Trying to create an already created platform view #45695

[ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: PlatformException(error, java.lang.IllegalStateException: Trying to create an already created platform view, view id: 0

Flutter doctor -v

[✓] Flutter (Channel stable, v1.12.13+hotfix.5, on Linux, locale en_IN)
    • Flutter version 1.12.13+hotfix.5 at /home/asus/Documents/Flutter_SDK/flutter
    • Framework revision 27321ebbad (2 weeks ago), 2019-12-10 18:15:01 -0800
    • Engine revision 2994f7e1e6
    • Dart version 2.7.0

[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
    • Android SDK at /home/asus/Android/Sdk
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-29, build-tools 29.0.2
    • Java binary at: /snap/android-studio/81/android-studio/jre/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)
    • All Android licenses accepted.

[✓] Android Studio (version 3.5)
    • Android Studio at /snap/android-studio/81/android-studio
    • Flutter plugin version 42.1.1
    • Dart plugin version 191.8593
    • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)

[✓] Connected device (1 available)
    • vivo 1723 • 49269ad3 • android-arm64 • Android 9 (API 28)

• No issues found!

Body:
I also had the same issue and using flutter clean didn't solve it for me (flutter version 1.12.13+hotfix 8)

But then, adding a unique key to the widget (not to its state) solved the issue for me.

minimum working code sample to demonstrate this.

import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Map not crashing demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: LocationScreen(),
    );
  }
}

class LocationScreen extends StatefulWidget
{
  final Key _mapKey = UniqueKey();
  @override
  _LocationScreenState createState() => _LocationScreenState();
}

class _LocationScreenState extends State<LocationScreen>
{
  @override
  Widget build(BuildContext context)
  {
    return Scaffold(
      appBar: AppBar(title: const Text('Map not crashing demo')),
      body: TheMap(key:widget._mapKey)
    );
  }
}

class TheMap extends StatefulWidget
{
  ///key is required, otherwise map crashes on hot reload
  TheMap({ @required Key key})
  :
  super(key:key);

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<TheMap>
{
  GoogleMapController _mapController ;

  void _onMapCreated(GoogleMapController controller) {
    _mapController = controller;
  }
  @override
  Widget build(BuildContext context)
  {
    return Scaffold(
      //also this avoids it crashing/breaking when the keyboard is up
      resizeToAvoidBottomInset: false,
      body: GoogleMap(
          onMapCreated: _onMapCreated,
          initialCameraPosition: CameraPosition(
            target: const LatLng(30.0925973,31.3219982),
            zoom: 11.0,
          ),
        )
    );
  }
}


答:
You can use a Shared ViewModel (https://developer.android.com/topic/libraries/architecture/viewmodel#sharing)

It would be alive while the activity is and all child fragments can access it.

A LiveData in a Shared ViewModel, for example, could be listened to in all the fragments. If one of those fragments change the data all others would get that change.

Title: Communicating between Activities and Fragments when using Navigation Architecture Component

Body:
I want to let the host Activity know when something happens in a Fragment. Traditionally, I would have an interface with a callback that the Fragment can call, but now we are ofc using the navigation architecture component.

Is there a way to pass a reference to the host activity down to the fragments or how would I otherwise solve the "Communication between activities and fragments" situation?

Thanks!