问:
JavaFx: How to properly fire updateItem in a TableCell
I have to implement a lot of custom TableCell which behavior relies on the model's change. I could manage to get somehow the expected result, but I think in many cases it was a workaround rather a really good solution.
I have used bindings/listeners to achieve the expected result, but the problem I face is that I may add the listeners/bind the properties multiple times and it can create memory leaks.

Here is an example what I mean.

Controller:

```<code>public class Controller implements Initializable {

    @FXML private TableView<Model> table;
    @FXML private TableColumn<Model, String> column;
    @FXML private Button change;

    @Override
    public void initialize(URL location, ResourceBundle resources) {

        column.setCellValueFactory(data -> data.getValue().text);
        column.setCellFactory(cell -> new ColoredTextCell());

        Model apple = new Model("Apple", "#8db600");

        table.getItems().add(apple);
        table.getItems().add(new Model("Banana", "#ffe135"));

        change.setOnAction(event -> apple.color.setValue("#ff0800"));

    }

    @Getter
    private class Model {
        StringProperty text;
        StringProperty color;

        private Model(String text, String color) {
            this.text = new SimpleStringProperty(text);
            this.color = new SimpleStringProperty(color);
        }
    }

    private class ColoredTextCell extends TableCell<Model, String> {

        @Override
        protected void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);
            if (empty || getTableRow() == null || getTableRow().getItem() == null) {
                setGraphic(null);
                return;
            }
            Model model = (Model) getTableRow().getItem();
            Text text = new Text(item);
            text.setFill(Color.web(model.getColor().getValue()));

            // This way I add the listener evey item updateItem is called.
            model.getColor().addListener((observable, oldValue, newValue) -> {
                if (newValue != null) {
                    text.setFill(Color.web(newValue));
                } else {
                    text.setFill(Color.BLACK);
                }
            });
            setGraphic(text);
        }
    }

}
</code>```

FXML:

```<code><?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Button?>
<AnchorPane xmlns="http://javafx.com/javafx"
            xmlns:fx="http://javafx.com/fxml"
            fx:controller="stackoverflow.tabpane.Controller">
    <VBox>
        <Button fx:id="change" text="Change color"/>
        <TableView fx:id="table">
            <columns>
                <TableColumn fx:id="column" prefWidth="200"/>
            </columns>
        </TableView>
    </VBox>
</AnchorPane>
</code>```

Since the color property isn't directly observed by the cell the updateItem is not called if it changes, so I have to listen to somehow.
I would need that the updateItem to be triggered after the color is changed. This would result a single call to the content of the listener.

Is there any way to listen to another change of the model in the same cell, or call the update item somehow, so the change gets rendered.

答:
Using listeners and bindings won't cause any issues so long as you remember to remove them when they're no longer needed. To make it even safer, you should use weak listeners (bindings use weak listeners). As you want to change the cell's text's color based on a different property of the row's item, I think using a binding will be easier. Note that TableCell inherits from Labeled which means it has a textFill property; there's no need to create a Text node to change the color of the text.

Here's an example:

```<code>import javafx.beans.binding.Bindings;
import javafx.scene.control.TableCell;
import javafx.scene.paint.Color;

public class ColoredTextCell extends TableCell<Model, String> {

    @Override
    protected void updateItem(String item, boolean empty) {
        super.updateItem(item, empty);

        /*
         * I was getting a NullPointerException without the "getTableRow() == null"
         * check. I find it strange that a TableCell's "updateItem" method would be
         * invoked before it was part of a TableRow... but the added null check seems
         * to solve the problem (at least when only having two items in the table and
         * no scrolling).
         */
        if (empty || item == null || getTableRow() == null) {
            setText(null);
            textFillProperty().unbind();
        } else {
            setText(item);

            Model rowItem = getTableRow().getItem();
            textFillProperty().bind(Bindings.createObjectBinding(
                    () -> Color.valueOf(rowItem.getColor()),
                    rowItem.colorProperty()
            ));
        }
    }

}
</code>```

The call to textFillProperty().unbind() will prevent a memory leak. And when binding a property the previous binding, if any, will be removed. If you're really paranoid you can call unbind() before bind(...) as well. And if you're really, really paranoid then you can store the ObjectBinding in a field and call dispose() when appropriate (and even null it out).

Body:
I have to implement a lot of custom TableCell which behavior relies on the model's change. I could manage to get somehow the expected result, but I think in many cases it was a workaround rather a really good solution.
I have used bindings/listeners to achieve the expected result, but the problem I face is that I may add the listeners/bind the properties multiple times and it can create memory leaks.

Here is an example what I mean.

Controller:

public class Controller implements Initializable {

    @FXML private TableView<Model> table;
    @FXML private TableColumn<Model, String> column;
    @FXML private Button change;

    @Override
    public void initialize(URL location, ResourceBundle resources) {

        column.setCellValueFactory(data -> data.getValue().text);
        column.setCellFactory(cell -> new ColoredTextCell());

        Model apple = new Model("Apple", "#8db600");

        table.getItems().add(apple);
        table.getItems().add(new Model("Banana", "#ffe135"));

        change.setOnAction(event -> apple.color.setValue("#ff0800"));

    }

    @Getter
    private class Model {
        StringProperty text;
        StringProperty color;

        private Model(String text, String color) {
            this.text = new SimpleStringProperty(text);
            this.color = new SimpleStringProperty(color);
        }
    }

    private class ColoredTextCell extends TableCell<Model, String> {

        @Override
        protected void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);
            if (empty || getTableRow() == null || getTableRow().getItem() == null) {
                setGraphic(null);
                return;
            }
            Model model = (Model) getTableRow().getItem();
            Text text = new Text(item);
            text.setFill(Color.web(model.getColor().getValue()));

            // This way I add the listener evey item updateItem is called.
            model.getColor().addListener((observable, oldValue, newValue) -> {
                if (newValue != null) {
                    text.setFill(Color.web(newValue));
                } else {
                    text.setFill(Color.BLACK);
                }
            });
            setGraphic(text);
        }
    }

}

FXML:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Button?>
<AnchorPane xmlns="http://javafx.com/javafx"
            xmlns:fx="http://javafx.com/fxml"
            fx:controller="stackoverflow.tabpane.Controller">
    <VBox>
        <Button fx:id="change" text="Change color"/>
        <TableView fx:id="table">
            <columns>
                <TableColumn fx:id="column" prefWidth="200"/>
            </columns>
        </TableView>
    </VBox>
</AnchorPane>

Since the color property isn't directly observed by the cell the updateItem is not called if it changes, so I have to listen to somehow.
I would need that the updateItem to be triggered after the color is changed. This would result a single call to the content of the listener.

Is there any way to listen to another change of the model in the same cell, or call the update item somehow, so the change gets rendered.

Body:
Using listeners and bindings won't cause any issues so long as you remember to remove them when they're no longer needed. To make it even safer, you should use weak listeners (bindings use weak listeners). As you want to change the cell's text's color based on a different property of the row's item, I think using a binding will be easier. Note that TableCell inherits from Labeled which means it has a textFill property; there's no need to create a Text node to change the color of the text.

Here's an example:

import javafx.beans.binding.Bindings;
import javafx.scene.control.TableCell;
import javafx.scene.paint.Color;

public class ColoredTextCell extends TableCell<Model, String> {

    @Override
    protected void updateItem(String item, boolean empty) {
        super.updateItem(item, empty);

        /*
         * I was getting a NullPointerException without the "getTableRow() == null"
         * check. I find it strange that a TableCell's "updateItem" method would be
         * invoked before it was part of a TableRow... but the added null check seems
         * to solve the problem (at least when only having two items in the table and
         * no scrolling).
         */
        if (empty || item == null || getTableRow() == null) {
            setText(null);
            textFillProperty().unbind();
        } else {
            setText(item);

            Model rowItem = getTableRow().getItem();
            textFillProperty().bind(Bindings.createObjectBinding(
                    () -> Color.valueOf(rowItem.getColor()),
                    rowItem.colorProperty()
            ));
        }
    }

}

The call to textFillProperty().unbind() will prevent a memory leak. And when binding a property the previous binding, if any, will be removed. If you're really paranoid you can call unbind() before bind(...) as well. And if you're really, really paranoid then you can store the ObjectBinding in a field and call dispose() when appropriate (and even null it out).


来源: stackexchange

问:
Ag grid: expand/collapse with pagination
I'm using detail-master feature and pagination. When I expend most bottom row, detail grid should stay on the same page as master row. Any good examples on how to do that? Thanks in advance.</p>

答:
Found a moderately satisfying solution: This only works if I set paginationPageSize manually; with paginationAutoPageSize=true bottom row expansion still goes to another page.</p>

```<code>onRowGroupOpened(event) {
        if (event.node.expanded) {
            this.gridOptions.api.paginationSetPageSize(++this.pageSize);
        } else {
            this.gridOptions.api.paginationSetPageSize(--this.pageSize);
        }
    },
</code>```

ContentLicense: CC BY-SA 4.0

Body:
Found a moderately satisfying solution: This only works if I set paginationPageSize manually; with paginationAutoPageSize=true bottom row expansion still goes to another page.

onRowGroupOpened(event) {
        if (event.node.expanded) {
            this.gridOptions.api.paginationSetPageSize(++this.pageSize);
        } else {
            this.gridOptions.api.paginationSetPageSize(--this.pageSize);
        }
    },


问:
CMake build with gcc/g++ fails on Windows
I've installed CMake 3.14.4 (from cmake-3.14.4-win64-x64.msi) and GCC 5.1.0 (from tdm64-gcc-5.1.0-2.exe) on Windows 7 Enterprise and 10 Home (64-bit).

I'm trying to build a .LIL from cpp/hpp source files github sources. The CMakeLists.txt refers to includes directory from the COTS install. A header file in the includes directory has this if-else and the CMake build always errors out by falling in the last else block below:

```<code># if defined(_M_AMD64)
#  include <wchar.h>
#  if BIP_CXX11_SUPPORT
typedef char16_t CciChar;
#  else
typedef wchar_t CciChar;
#  endif
typedef __int64 CciInt;
typedef unsigned __int64 CciCount;
#  define __CCI_WINDOWS__
# else
#  error The C plugin interface for IBM Integration Bus is only available
for 64-bit Windows x86-64 systems
#endif
</code>```

Steps:

```<code>1. c:\iib-swm\build>cmake -DIIB_INSTALL_DIR=C:\Progra~1\IBM\IIB\10.0.0.12
-G "MinGW Makefiles" ../source
-- The CXX compiler identification is GNU 5.1.0
-- Check for working CXX compiler: C:/software/C++Tools/tdm-
gcc/bin/g++.exe
-- Check for working CXX compiler: C:/software/C++Tools/tdm-
gcc/bin/g++.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: C:/iib-swm/build
</code>```

This is the content of CMakeSystem.cmake after this step:

```<code>set(CMAKE_HOST_SYSTEM "Windows-6.1.7601")
set(CMAKE_HOST_SYSTEM_NAME "Windows")
set(CMAKE_HOST_SYSTEM_VERSION "6.1.7601")
set(CMAKE_HOST_SYSTEM_PROCESSOR "AMD64")

set(CMAKE_SYSTEM "Windows-6.1.7601")
set(CMAKE_SYSTEM_NAME "Windows")
set(CMAKE_SYSTEM_VERSION "6.1.7601")
set(CMAKE_SYSTEM_PROCESSOR "AMD64")

set(CMAKE_CROSSCOMPILING "FALSE")

set(CMAKE_SYSTEM_LOADED 1)

2. c:\iib-swm\build>cmake --build .

   -- Configuring done
   -- Generating done
   -- Build files have been written to: C:/iib-swm/build
   [ 33%] Building CXX object
   CMakeFiles/statsdsw.dir/StatsdStatsWriter.cpp.obj
   In file included from
   C:/Progra~1/IBM/IIB/10.0.0.12/server/include/plugin/BipCci.h:14:0,
             from
   C:/Progra~1/IBM/IIB/10.0.0.12/server/include/plugin/BipCsi.h:14,
             from C:\iib-swm\source\StatsdStatsWriter.hpp:13,
             from C:\iib-swm\source\StatsdStatsWriter.cpp:10:
   C:/Progra~1/IBM/IIB/10.0.0.12/server/include/plugin/BipCos.h:170:4:
   error: #error The C plugin inter
   face for IBM Integration Bus is only available for 64-bit Windows x86-
   64 systems
   #  error The C plugin interface for IBM Integration Bus is only
   available for 64-bit Windows x86-64
   systems
      ^
   CMakeFiles\statsdsw.dir\build.make:62: recipe for target
   'CMakeFiles/statsdsw.dir/StatsdStatsWriter.
   cpp.obj' failed
   mingw32-make.exe[2]: ***
   [CMakeFiles/statsdsw.dir/StatsdStatsWriter.cpp.obj] Error 3
   CMakeFiles\Makefile2:71: recipe for target
   'CMakeFiles/statsdsw.dir/all' failed
   mingw32-make.exe[1]: *** [CMakeFiles/statsdsw.dir/all] Error 130
   Makefile:82: recipe for target 'all' failed
   mingw32-make.exe: *** [all] Error 130
</code>```

I just can't understand that even when CMake recognizes the system processor as AMD64, it doesn't translate to _M_AMD64 in the includes .h file? I've trawled CMake and related resources on the net. Tried running CMake as admin, shortened the path in which git project was cloned to without luck.

PS: My only brush with cpp was at Uni 15 years ago, so please have mercy my lords (and ladies) if I've missed to C the obvious.

答:
_M_AMD64 appears to be specific to Visual Studio compilers.  The question is confusing because it suggests that CMake is doing the pre-processing.  It doesn't.  You are using gcc. gcc doesn't appear to implement the Visual Studio specific pre-processor macros.

You'll either have to alter the code to work with gcc or define the missing macros yourself using a CMake command like target_compile_definitions.

Be aware that the README file says to use Visual Studio 2015 for building on Windows.

Body:
I've installed CMake 3.14.4 (from cmake-3.14.4-win64-x64.msi) and GCC 5.1.0 (from tdm64-gcc-5.1.0-2.exe) on Windows 7 Enterprise and 10 Home (64-bit).

I'm trying to build a .LIL from cpp/hpp source files github sources. The CMakeLists.txt refers to includes directory from the COTS install. A header file in the includes directory has this if-else and the CMake build always errors out by falling in the last else block below:

# if defined(_M_AMD64)
#  include <wchar.h>
#  if BIP_CXX11_SUPPORT
typedef char16_t CciChar;
#  else
typedef wchar_t CciChar;
#  endif
typedef __int64 CciInt;
typedef unsigned __int64 CciCount;
#  define __CCI_WINDOWS__
# else
#  error The C plugin interface for IBM Integration Bus is only available
for 64-bit Windows x86-64 systems
#endif

Steps:

1. c:\iib-swm\build>cmake -DIIB_INSTALL_DIR=C:\Progra~1\IBM\IIB\10.0.0.12
-G "MinGW Makefiles" ../source
-- The CXX compiler identification is GNU 5.1.0
-- Check for working CXX compiler: C:/software/C++Tools/tdm-
gcc/bin/g++.exe
-- Check for working CXX compiler: C:/software/C++Tools/tdm-
gcc/bin/g++.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: C:/iib-swm/build

This is the content of CMakeSystem.cmake after this step:

set(CMAKE_HOST_SYSTEM "Windows-6.1.7601")
set(CMAKE_HOST_SYSTEM_NAME "Windows")
set(CMAKE_HOST_SYSTEM_VERSION "6.1.7601")
set(CMAKE_HOST_SYSTEM_PROCESSOR "AMD64")

set(CMAKE_SYSTEM "Windows-6.1.7601")
set(CMAKE_SYSTEM_NAME "Windows")
set(CMAKE_SYSTEM_VERSION "6.1.7601")
set(CMAKE_SYSTEM_PROCESSOR "AMD64")

set(CMAKE_CROSSCOMPILING "FALSE")

set(CMAKE_SYSTEM_LOADED 1)

2. c:\iib-swm\build>cmake --build .

   -- Configuring done
   -- Generating done
   -- Build files have been written to: C:/iib-swm/build
   [ 33%] Building CXX object
   CMakeFiles/statsdsw.dir/StatsdStatsWriter.cpp.obj
   In file included from
   C:/Progra~1/IBM/IIB/10.0.0.12/server/include/plugin/BipCci.h:14:0,
             from
   C:/Progra~1/IBM/IIB/10.0.0.12/server/include/plugin/BipCsi.h:14,
             from C:\iib-swm\source\StatsdStatsWriter.hpp:13,
             from C:\iib-swm\source\StatsdStatsWriter.cpp:10:
   C:/Progra~1/IBM/IIB/10.0.0.12/server/include/plugin/BipCos.h:170:4:
   error: #error The C plugin inter
   face for IBM Integration Bus is only available for 64-bit Windows x86-
   64 systems
   #  error The C plugin interface for IBM Integration Bus is only
   available for 64-bit Windows x86-64
   systems
      ^
   CMakeFiles\statsdsw.dir\build.make:62: recipe for target
   'CMakeFiles/statsdsw.dir/StatsdStatsWriter.
   cpp.obj' failed
   mingw32-make.exe[2]: ***
   [CMakeFiles/statsdsw.dir/StatsdStatsWriter.cpp.obj] Error 3
   CMakeFiles\Makefile2:71: recipe for target
   'CMakeFiles/statsdsw.dir/all' failed
   mingw32-make.exe[1]: *** [CMakeFiles/statsdsw.dir/all] Error 130
   Makefile:82: recipe for target 'all' failed
   mingw32-make.exe: *** [all] Error 130

I just can't understand that even when CMake recognizes the system processor as AMD64, it doesn't translate to _M_AMD64 in the includes .h file? I've trawled CMake and related resources on the net. Tried running CMake as admin, shortened the path in which git project was cloned to without luck.

PS: My only brush with cpp was at Uni 15 years ago, so please have mercy my lords (and ladies) if I've missed to C the obvious.


问:
is there any problem whih my code for adding new cattegories?
I have written this code for my eshop so that i can add new categories for the products that i sell.Can anyone please tell me if my code is correct so that i can upload it? Or if there is any problem with it? Can you tell me so that I can fix it and make it work properly?</p>

```<code><form action="" method="post" style="padding:80px;">

<b>Insert New Category:</b>
<input type="text" name="new_cat" required/>
<input type="submit" name="add_cat" value="Add Category" />

</form>

<?php
    if(isset($_POST['add_cat'])){

    $new_cat = $_POST['new_cat'];

    $insert_cat = "insert into categories (cat_title) values ('$new_cat')";
    $run_cat = mysqli_query($con, $insert_cat);

    if($run_cat){

    echo "<script>alert('New Category has been inserted!')</script>";
    echo "<script>window.open('eshop.php?view_cats','_self')</script>";
    }
    }
?>
</code>```

答:
Use this to prevent the SQL injections like Jonnix said in the comments:</p>

```<code>$new_cat = mysqli_real_escape_string($con, $_POST['new_cat']);
</code>```

Body:
I have written this code for my eshop so that i can add new categories for the products that i sell.Can anyone please tell me if my code is correct so that i can upload it? Or if there is any problem with it? Can you tell me so that I can fix it and make it work properly?

<form action="" method="post" style="padding:80px;">

Insert New Category:
<input type="text" name="new_cat" required/>
<input type="submit" name="add_cat" value="Add Category" />

</form>

<?php
    if(isset($_POST['add_cat'])){

    $new_cat = $_POST['new_cat'];

    $insert_cat = "insert into categories (cat_title) values ('$new_cat')";
    $run_cat = mysqli_query($con, $insert_cat);

    if($run_cat){

    echo "";
    echo "";
    }
    }
?>

Body:
Use this to prevent the SQL injections like Jonnix said in the comments:

$new_cat = mysqli_real_escape_string($con, $_POST['new_cat']);


问:
Runtime checking that switch is exhaustive (when it's compile time exhaustive)
I have a switch statement that covers all the compile time possibilities but, since the value can be user supplied, I want handle unexpected values in runtime.

This seems to be a place where typescript's type inference is too good, it assigns type never (since from the compilers perspective this should never happen) and won't let me access any of its fields.

Simplified example:

```<code>type Circle = { shape: "circle", radius: number };
type Rectangle = { shape: "rectangle", length: number, width: number };

function area(shape: Circle | Rectangle): number {
    switch (shape.shape) {
        case "circle": return Math.PI * shape.radius * shape.radius;
        case "rectangle": return shape.length * shape.width;
    }
    throw new Error(`Unexpected shape '${shape.shape}'`); // Error: Property 'shape' does not exist on type 'never'.
}
</code>```

Is there an elegant way to fix the last line? (more elegant than casting to any or using subscript operator).

答:
this page offers a solution:
https://www.typescriptlang.org/docs/handbook/advanced-types.html

Adapted for your example:

```<code>
    type Circle = { shape: "circle", radius: number };
    type Rectangle =  { shape: "rectangle", length: number, width: number };

    function throwOnNever(x: {shape: string}): never {
        throw new Error(`Unexpected shape: ${x.shape}`);
    }

    function area(shape: Circle | Rectangle): number {
        switch (shape.shape) {
            case "circle": return Math.PI * shape.radius * shape.radius;
            case "rectangle": return shape.length * shape.width;
            default: return throwOnNever(shape);
        }
    }

</code>```

Body:
I have a switch statement that covers all the compile time possibilities but, since the value can be user supplied, I want handle unexpected values in runtime.

This seems to be a place where typescript's type inference is too good, it assigns type never (since from the compilers perspective this should never happen) and won't let me access any of its fields.

<a href="https://www.typescriptlang.org/play/#src=type%20Circle%20%3D%20%7B%20shape%3A%20%22circle%22%2C%20radius%3A%20number%20%7D%3B%0D%0Atype%20Rectangle%20%3D%20%7B%20shape%3A%20%22rectangle%22%2C%20length%3A%20number%2C%20width%3A%20number%20%7D%3B%0D%0A%0D%0Afunction%20area(shape%3A%20Circle%20%7C%20Rectangle)%3A%20number%20%7B%0D%0A%20%20%20%20switch%20(shape.shape)%20%7B%0D%0A%20%20%20%20%20%20%20%20case%20%22circle%22%3A%20return%20Math.PI%20*%20shape.radius%20*%20shape.radius%3B%0D%0A%20%20%20%20%20%20%20%20case%20%22rectangle%22%3A%20return%20shape.length%20*%20shape.width%3B%0D%0A%20%20%20%20%7D%0D%0A%20%20%20%20throw%20new%20Error(%60Unexpected%20shape%20'%24%7Bshape.shape%7D'%60)%3B%0D%0A%7D" rel="nofollow noreferrer">Simplified example:

type Circle = { shape: "circle", radius: number };
type Rectangle = { shape: "rectangle", length: number, width: number };

function area(shape: Circle | Rectangle): number {
    switch (shape.shape) {
        case "circle": return Math.PI * shape.radius * shape.radius;
        case "rectangle": return shape.length * shape.width;
    }
    throw new Error(`Unexpected shape '${shape.shape}'`); // Error: Property 'shape' does not exist on type 'never'.
}

Is there an elegant way to fix the last line? (more elegant than casting to any or using subscript operator).

Body:
this page offers a solution:
https://www.typescriptlang.org/docs/handbook/advanced-types.html

Adapted for your example:

    type Circle = { shape: "circle", radius: number };
    type Rectangle =  { shape: "rectangle", length: number, width: number };

    function throwOnNever(x: {shape: string}): never {
        throw new Error(`Unexpected shape: ${x.shape}`);
    }

    function area(shape: Circle | Rectangle): number {
        switch (shape.shape) {
            case "circle": return Math.PI * shape.radius * shape.radius;
            case "rectangle": return shape.length * shape.width;
            default: return throwOnNever(shape);
        }
    }


问:
How to request authentication from custom middleware in ASP.NET Core 2.0
I have two custom ASP.NET Core middlewares: one for authentication (that registers its own authentication scheme) and a second one for some business work.

How can I use the authentication middleware in another middleware? I can use authentication easily in an MVC like that:

```<code> services.AddMvc(config =>
 {
     var policy = new AuthorizationPolicyBuilder()
                      .RequireAuthenticatedUser()
                      .Build();
     config.Filters.Add(new AuthorizeFilter(policy));
 });
</code>```

I can also provide my own AuthenticationSchemeProvider to use different authentication schemes based on the requested URL. But the authentication middleware only runs for MVC controllers. I want it to run also before my custom middleware runs. Is it possible to do that?

答:
This is based on Rython's answer for the specific case of using Windows Authentication, but also allows designed controllers to use other type of authentication:

```<code>/// <summary>
/// checks if current request resource can be accesses without being Windows-authenticated
/// </summary>
/// <param name="context">http context</param>
/// <returns>true if non-Windows is allowed. Otherwise, false</returns>
public static bool IsAllowedWithoutWindowsAuth(HttpContext context)
{
    bool isAllowedWithoutWindowsAuth = context.Request.Method == "OPTIONS" ||
                                       AllowedControllers.Any(c =>
                                       {
                                           string path = context.Request.Path.ToString();
                                           return path.StartsWith(c, StringComparison.InvariantCulture);
                                       });
    return isAllowedWithoutWindowsAuth;
}

// custom middleware code
public async Task Invoke(HttpContext context)
{
    // anonymous path, skipping
    if (IsAllowedWithoutWindowsAuth(context))
    {
        await _next(context);
        return;
    }

    if (!context.User.Identity.IsAuthenticated)
    {
        await context.ChallengeAsync("Windows");
        return;
    }

    // other code here
    await _next(context);
 }
</code>```

Body:
I have two custom ASP.NET Core middlewares: one for authentication (that registers its own authentication scheme) and a second one for some business work.

How can I use the authentication middleware in another middleware? I can use authentication easily in an MVC like that:

 services.AddMvc(config =>
 {
     var policy = new AuthorizationPolicyBuilder()
                      .RequireAuthenticatedUser()
                      .Build();
     config.Filters.Add(new AuthorizeFilter(policy));
 });

I can also provide my own AuthenticationSchemeProvider to use different authentication schemes based on the requested URL. But the authentication middleware only runs for MVC controllers. I want it to run also before my custom middleware runs. Is it possible to do that?

Body:
This is based on Rython's answer for the specific case of using Windows Authentication, but also allows designed controllers to use other type of authentication:

/// <summary>
/// checks if current request resource can be accesses without being Windows-authenticated
/// </summary>
/// <param name="context">http context</param>
/// <returns>true if non-Windows is allowed. Otherwise, false</returns>
public static bool IsAllowedWithoutWindowsAuth(HttpContext context)
{
    bool isAllowedWithoutWindowsAuth = context.Request.Method == "OPTIONS" ||
                                       AllowedControllers.Any(c =>
                                       {
                                           string path = context.Request.Path.ToString();
                                           return path.StartsWith(c, StringComparison.InvariantCulture);
                                       });
    return isAllowedWithoutWindowsAuth;
}

// custom middleware code
public async Task Invoke(HttpContext context)
{
    // anonymous path, skipping
    if (IsAllowedWithoutWindowsAuth(context))
    {
        await _next(context);
        return;
    }

    if (!context.User.Identity.IsAuthenticated)
    {
        await context.ChallengeAsync("Windows");
        return;
    }

    // other code here
    await _next(context);
 }


问:
Killing EXCEL.exe Process from C# in a Windows Service
I have a windows service that opens up an Excel spreadsheet via  the Microsoft.Office.Interop.Excel.Application object.

```<code>Application xlApp = new Application();
Workbook workbook = xlApp.Workbooks.Open(fileName, 2, false);
...
...
workbook.Close();
xlApp.Quit();
</code>```

I would like to kill the EXCEL.exe process that is left running after it is done working with the workbook.

I've tried the following with no success...

```<code>// This returns a processId of 0
IntPtr processId;
GetWindowThreadProcessId(new IntPtr(xlApp.Hwnd), out processId);
Process p = Process.GetProcessById(processId.ToInt32());
p.Kill();
</code>```

Anyone have any ideas as to how I can do this via a Windows Service?

答:
After much reading and frustration I've found a solution!

All credit goes to dotNetkow, nightcoder and Mike Rosenblum for their solutions on this post: How do I properly clean up Excel interop objects?

Here is what I did...

1. Changed build mode of the project to "Release" (in DEBUG mode, COM objects have a hard time disposing of their references.

2. Removed all double dot expressions (all COM objects should be tied to a variable so they can be released)

3. Calling GC.Collect(), GC.WaitForPendingFinalizers(), and Marshal.FinalReleaseComObject() explicitly in a finally block

Here is the acutal code I am using:

```<code>Application xlApp = null;
Workbooks workbooks = null;
Workbook workbook = null;
Worksheet sheet = null;
Range r = null;
object obj = null;

try
{
    xlApp = new Application();
    xlApp.DisplayAlerts = false;
    xlApp.AskToUpdateLinks = false;
    workbooks = xlApp.Workbooks;
    workbook = workbooks.Open(fileName, 2, false);
    sheet = workbook.Worksheets[1];

    r = sheet.get_Range("F19");
    obj = r.get_Value(XlRangeValueDataType.xlRangeValueDefault);
}
finally
{
    GC.Collect();
    GC.WaitForPendingFinalizers();
    if (value != null) Marshal.FinalReleaseComObject(value);
    if (r != null) Marshal.FinalReleaseComObject(r);
    if (sheet != null) Marshal.FinalReleaseComObject(sheet);
    if (workbooks != null) Marshal.FinalReleaseComObject(workbooks);
    if (workbook != null)
    {
        workbook.Close(Type.Missing, Type.Missing, Type.Missing);
        Marshal.FinalReleaseComObject(workbook);
    }
    if (xlApp != null)
    {
        xlApp.Quit();
        Marshal.FinalReleaseComObject(xlApp);
    }
}
</code>```

ContentLicense: CC BY-SA 3.0

Body:
I have a windows service that opens up an Excel spreadsheet via  the Microsoft.Office.Interop.Excel.Application object.

Application xlApp = new Application();
Workbook workbook = xlApp.Workbooks.Open(fileName, 2, false);
...
...
workbook.Close();
xlApp.Quit();

I would like to kill the EXCEL.exe process that is left running after it is done working with the workbook.

I've tried the following with no success...

// This returns a processId of 0
IntPtr processId;
GetWindowThreadProcessId(new IntPtr(xlApp.Hwnd), out processId);
Process p = Process.GetProcessById(processId.ToInt32());
p.Kill();

Anyone have any ideas as to how I can do this via a Windows Service?

Body:
After much reading and frustration I've found a solution!

All credit goes to dotNetkow, nightcoder and Mike Rosenblum for their solutions on this post: How do I properly clean up Excel interop objects?

Here is what I did...

1. Changed build mode of the project to "Release" (in DEBUG mode, COM objects have a hard time disposing of their references.

2. Removed all double dot expressions (all COM objects should be tied to a variable so they can be released)

3. Calling GC.Collect(), GC.WaitForPendingFinalizers(), and Marshal.FinalReleaseComObject() explicitly in a finally block

Here is the acutal code I am using:

Application xlApp = null;
Workbooks workbooks = null;
Workbook workbook = null;
Worksheet sheet = null;
Range r = null;
object obj = null;

try
{
    xlApp = new Application();
    xlApp.DisplayAlerts = false;
    xlApp.AskToUpdateLinks = false;
    workbooks = xlApp.Workbooks;
    workbook = workbooks.Open(fileName, 2, false);
    sheet = workbook.Worksheets[1];

    r = sheet.get_Range("F19");
    obj = r.get_Value(XlRangeValueDataType.xlRangeValueDefault);
}
finally
{
    GC.Collect();
    GC.WaitForPendingFinalizers();
    if (value != null) Marshal.FinalReleaseComObject(value);
    if (r != null) Marshal.FinalReleaseComObject(r);
    if (sheet != null) Marshal.FinalReleaseComObject(sheet);
    if (workbooks != null) Marshal.FinalReleaseComObject(workbooks);
    if (workbook != null)
    {
        workbook.Close(Type.Missing, Type.Missing, Type.Missing);
        Marshal.FinalReleaseComObject(workbook);
    }
    if (xlApp != null)
    {
        xlApp.Quit();
        Marshal.FinalReleaseComObject(xlApp);
    }
}


问:
List<Tasks> dont do anything when i run code but if i step through it works
When i execute the code, inspecting after WhenAll the idList is empty, if i step through it using breakpoints after the WhenAll everything works as expected.

This code is within a non-async method.

Its as if letting it run on its own is not starting the tasks.

```<code>var currentPage = 1;
List<Result> idList = new List<Result>();

var response = this.GetDocuments(currentPage).Result;
//idList.AddRange(response.results);

var tasks = new List<Task>();

for (var i = 0; i < response.meta.page.total_pages; ++i)
{
    var t = new Task(() =>
    {
        response = this.GetDocuments(i+1).Result;
        idList.AddRange(response.results);
    });
    tasks.Add(t);
    t.Start();
}

 Task.WhenAll(tasks).Wait();

 public async Task<ResponseObject> GetDocuments(int currentPage)
        {
            var result = await httpClient.GetAsync($"api/as/v1/engines/urlname/documents/list?page[current]={currentPage}").ConfigureAwait(false);

            if (!result.IsSuccessStatusCode)
            {
                loggly.Error($"Exception: ScheduledJobBase, IndexPages, failed when getting documents from Swiftype, response: { result }");
                return null;
            }

            return await result.Content.ReadAsAsync<ResponseObject>().ConfigureAwait(false); ;
        }
</code>```

答:
Although the ideal scenario would be to convert the method return type to a Task and return or await the result of Task.WhenAll, if the method must remain non-async, then call .Wait() on the result of the Task.WhenAll call like so:

```<code>Task.WhenAll(tasks).Wait();
</code>```

Body:
When i execute the code, inspecting after WhenAll the idList is empty, if i step through it using breakpoints after the WhenAll everything works as expected.

This code is within a non-async method.

Its as if letting it run on its own is not starting the tasks.

var currentPage = 1;
List<Result> idList = new List<Result>();

var response = this.GetDocuments(currentPage).Result;
//idList.AddRange(response.results);

var tasks = new List<Task>();

for (var i = 0; i < response.meta.page.total_pages; ++i)
{
    var t = new Task(() =>
    {
        response = this.GetDocuments(i+1).Result;
        idList.AddRange(response.results);
    });
    tasks.Add(t);
    t.Start();
}

 Task.WhenAll(tasks).Wait();

 public async Task<ResponseObject> GetDocuments(int currentPage)
        {
            var result = await httpClient.GetAsync($"api/as/v1/engines/urlname/documents/list?page[current]={currentPage}").ConfigureAwait(false);

            if (!result.IsSuccessStatusCode)
            {
                loggly.Error($"Exception: ScheduledJobBase, IndexPages, failed when getting documents from Swiftype, response: { result }");
                return null;
            }

            return await result.Content.ReadAsAsync<ResponseObject>().ConfigureAwait(false); ;
        }

Body:
Although the ideal scenario would be to convert the method return type to a Task and return or await the result of Task.WhenAll, if the method must remain non-async, then call .Wait() on the result of the Task.WhenAll call like so:

Task.WhenAll(tasks).Wait();


答:
This seems to work. It assumes that

The first line that contains numbers is that immediately after the line that begins with 'dd-mm-yyyy'.

The last line that contains numbers is two lines above the line that begins with '# Key Parameter'.

Code:

```<code>t = fileread('file.txt'); % Read the file as a character vector
t = strsplit(t, {'\r' '\n'}, 'CollapseDelimiters', true); % Split on newline or carriage
    % return. This gives a cell array with each line in a cell
ind_start = find(cellfun(@any, regexp(t, '^dd-mm-yyyy', 'once')), 1) + 1; % index of
    % line where the numbers begin: immediately after the line 'dd-mm-yyyy...'
ind_end = find(cellfun(@any, regexp(t, '^# Key Parameter', 'once')), 1) - 2; % index of
    % line where numbers end: two lines before the line '# Key Parameter...'
result = cellfun(@(u) sscanf(u, '%d-%d-%d %02d:%02d:%02d.%d.%d.%d.%d %f %f %f %f').', ...
    t(ind_start:ind_end), 'UniformOutput', false);
    % Apply sscanf to each line. The format specifier uses %d where needed to prevent
    % the dot from being interpreted as part of a floating point number. Also, the
    % possible existence of leading zeros needs to be taken into account. The result is
    % a cell array, where each cell contains a numeric vector corresponding to one line
result = cell2mat(result.'); % convert the result to a numerical array
</code>```

Title: Using matlab to extract data in between text

Body:
I am trying to export a set of data and I am pretty knew to this. The data in question has this structure:

#              ************************************
#              *****    GLOBAL ATTRIBUTES    ******
#              ************************************
#

#     PROJECT                         THEMIS
#
UT                                             UT      BX_FGL-D      BY_FGL-D      BZ_FGL-D
                                                         (@_1_)        (@_2_)        (@_3_)
dd-mm-yyyy hh:mm:ss.mil.mic.nan.pic           sec        nT_GSE        nT_GSE        nT_GSE
21-05-2015 00:00:00.223.693.846.740   1.43208E+09       1.14132       9.14226       27.1446
21-05-2015 00:00:00.473.693.845.716   1.43208E+09       1.11194       9.16192       27.1798
21-05-2015 00:00:00.723.693.844.692   1.43208E+09       1.12992       9.11103       27.1595
21-05-2015 00:00:00.973.693.843.668   1.43208E+09       1.15966       9.15324       27.1589
21-05-2015 00:00:01.223.693.846.740   1.43208E+09       1.20576       9.14420       27.1388
21-05-2015 00:09:59.973.693.843.668   1.43208E+09       1.97445       8.66407       26.1837
#
# Key Parameter and Survey data (labels K0,K1,K2) are preliminary browse data.
# Generated by CDAWeb on: Mon May 27 06:01:29 2019

I require those written between “dd-mm-yyyy….” and “#  # Key Parameter” to be exported to columns.
E.g. , the first line 21-05-2015 00:00:00.223.693.846.740   1.43208E+09       1.14132       9.14226       27.1446, has to exported into 21, 05,2015, 00,00,00,223,693,846,740, 1.43208E+09,1.14132, 9.14226 and 27.1446.

Similar question is tackled at Use MATLAB to extract data beyond "Data starts on next line:" in text-file but I believe my data is complicated and I could not do further. The best I could do was to write a part of code to read till “dd-mm-yyyy”:

clear;clc;close all;
f = fopen('dataa_file.txt');
line = fgetl(f);
while isempty(strfind(line, 'nT_GSE'))
    if line == -1 %// If we reach the end of the file, get out
        break;
    end
    line = fgetl(f);
end

Any help will be deeply appreciated…

Body:
This seems to work. It assumes that

The first line that contains numbers is that immediately after the line that begins with 'dd-mm-yyyy'.

The last line that contains numbers is two lines above the line that begins with '# Key Parameter'.

Code:

t = fileread('file.txt'); % Read the file as a character vector
t = strsplit(t, {'\r' '\n'}, 'CollapseDelimiters', true); % Split on newline or carriage
    % return. This gives a cell array with each line in a cell
ind_start = find(cellfun(@any, regexp(t, '^dd-mm-yyyy', 'once')), 1) + 1; % index of
    % line where the numbers begin: immediately after the line 'dd-mm-yyyy...'
ind_end = find(cellfun(@any, regexp(t, '^# Key Parameter', 'once')), 1) - 2; % index of
    % line where numbers end: two lines before the line '# Key Parameter...'
result = cellfun(@(u) sscanf(u, '%d-%d-%d %02d:%02d:%02d.%d.%d.%d.%d %f %f %f %f').', ...
    t(ind_start:ind_end), 'UniformOutput', false);
    % Apply sscanf to each line. The format specifier uses %d where needed to prevent
    % the dot from being interpreted as part of a floating point number. Also, the
    % possible existence of leading zeros needs to be taken into account. The result is
    % a cell array, where each cell contains a numeric vector corresponding to one line
result = cell2mat(result.'); % convert the result to a numerical array


问:
How to implement shared transition element from RecyclerView item to Fragment with Android Navigation Component?
I have a pretty straightforward case. I want to implement shared element transition between an item in recyclerView and fragment. I'm using android navigation component in my app.

There is an article about shared transition on developer.android and topic on stackoverflow but this solution works only for view that located in fragment layout that starts transition and doesn't work for items from RecyclerView. Also there is a lib on github but i don't want to rely on 3rd party libs and do it by myself.

Is there some solution for this? Maybe it should work and this is just a bug? But I haven't found any information about it.

code sample:

transition start

```<code>class TransitionStartFragment: Fragment() {

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    return inflater.inflate(R.layout.fragment_transition_start, container, false)
    }

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    val testData = listOf("one", "two", "three")
    val adapter = TestAdapter(testData, View.OnClickListener { transitionWithTextViewInRecyclerViewItem(it) })
    val recyclerView = view.findViewById<RecyclerView>(R.id.test_list)
    recyclerView.adapter = adapter
    val button = view.findViewById<Button>(R.id.open_transition_end_fragment)
    button.setOnClickListener { transitionWithTextViewInFragment() }
    }

private fun transitionWithTextViewInFragment(){
    val destination = TransitionStartFragmentDirections.openTransitionEndFragment()
    val extras = FragmentNavigatorExtras(transition_start_text to "transitionTextEnd")
    findNavController().navigate(destination, extras)
    }

private fun transitionWithTextViewInRecyclerViewItem(view: View){
    val destination = TransitionStartFragmentDirections.openTransitionEndFragment()
    val extras = FragmentNavigatorExtras(view to "transitionTextEnd")
    findNavController().navigate(destination, extras)
   }
</code>```

}

layout

```<code><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<TextView
    android:id="@+id/transition_start_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="transition"
    android:transitionName="transitionTextStart"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<Button
    android:id="@+id/open_transition_end_fragment"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintTop_toBottomOf="@id/transition_start_text"
    android:text="open transition end fragment" />

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/test_list"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_constraintTop_toBottomOf="@id/open_transition_end_fragment"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</code>```

adapter for recyclerView

```<code>class TestAdapter(
    private val items: List<String>,
    private val onItemClickListener: View.OnClickListener
) : RecyclerView.Adapter<TestAdapter.ViewHodler>() {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHodler {
    return ViewHodler(LayoutInflater.from(parent.context).inflate(R.layout.item_test, parent, false))
    }

override fun getItemCount(): Int {
    return items.size
    }

override fun onBindViewHolder(holder: ViewHodler, position: Int) {
    val item = items[position]
    holder.transitionText.text = item
    holder.itemView.setOnClickListener { onItemClickListener.onClick(holder.transitionText) }

    }

class ViewHodler(itemView: View) : RecyclerView.ViewHolder(itemView) {
    val transitionText = itemView.findViewById<TextView>(R.id.item_test_text)
    }
}
</code>```

in onItemClick I pass the textView form item in recyclerView for transition

transition end

```<code>class TransitionEndFragment : Fragment() {

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    setUpTransition()
    return inflater.inflate(R.layout.fragment_transition_end, container, false)
    }

private fun setUpTransition(){
    sharedElementEnterTransition = TransitionInflater.from(context).inflateTransition(android.R.transition.move)

    }
}
</code>```

layout

```<code><androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<TextView
    android:id="@+id/transition_end_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="transition"
    android:transitionName="transitionTextEnd"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
</code>```

fun transitionWithTextViewInFragment() - has transition.

fun transitionWithTextViewInRecyclerViewItem(view: View) - no transition.

答:
To solve the return transition problem you need to add this lines on the Source Fragment (the fragment with the recycler view) where you initialize your recycler view</p>

```<code>// your recyclerView
recyclerView.apply {
                ...
                adapter = myAdapter
                postponeEnterTransition()
                viewTreeObserver
                    .addOnPreDrawListener {
                        startPostponedEnterTransition()
                        true
                    }
}
</code>```

Body:
I have a pretty straightforward case. I want to implement shared element transition between an item in recyclerView and fragment. I'm using android navigation component in my app.

There is an article about shared transition on developer.android and topic on stackoverflow but this solution works only for view that located in fragment layout that starts transition and doesn't work for items from RecyclerView. Also there is a lib on github but i don't want to rely on 3rd party libs and do it by myself.

Is there some solution for this? Maybe it should work and this is just a bug? But I haven't found any information about it.

code sample:

transition start

class TransitionStartFragment: Fragment() {

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    return inflater.inflate(R.layout.fragment_transition_start, container, false)
    }

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    val testData = listOf("one", "two", "three")
    val adapter = TestAdapter(testData, View.OnClickListener { transitionWithTextViewInRecyclerViewItem(it) })
    val recyclerView = view.findViewById<RecyclerView>(R.id.test_list)
    recyclerView.adapter = adapter
    val button = view.findViewById<Button>(R.id.open_transition_end_fragment)
    button.setOnClickListener { transitionWithTextViewInFragment() }
    }

private fun transitionWithTextViewInFragment(){
    val destination = TransitionStartFragmentDirections.openTransitionEndFragment()
    val extras = FragmentNavigatorExtras(transition_start_text to "transitionTextEnd")
    findNavController().navigate(destination, extras)
    }

private fun transitionWithTextViewInRecyclerViewItem(view: View){
    val destination = TransitionStartFragmentDirections.openTransitionEndFragment()
    val extras = FragmentNavigatorExtras(view to "transitionTextEnd")
    findNavController().navigate(destination, extras)
   }

}

layout

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<TextView
    android:id="@+id/transition_start_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="transition"
    android:transitionName="transitionTextStart"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<Button
    android:id="@+id/open_transition_end_fragment"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintTop_toBottomOf="@id/transition_start_text"
    android:text="open transition end fragment" />

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/test_list"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_constraintTop_toBottomOf="@id/open_transition_end_fragment"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />

adapter for recyclerView

class TestAdapter(
    private val items: List<String>,
    private val onItemClickListener: View.OnClickListener
) : RecyclerView.Adapter<TestAdapter.ViewHodler>() {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHodler {
    return ViewHodler(LayoutInflater.from(parent.context).inflate(R.layout.item_test, parent, false))
    }

override fun getItemCount(): Int {
    return items.size
    }

override fun onBindViewHolder(holder: ViewHodler, position: Int) {
    val item = items[position]
    holder.transitionText.text = item
    holder.itemView.setOnClickListener { onItemClickListener.onClick(holder.transitionText) }

    }

class ViewHodler(itemView: View) : RecyclerView.ViewHolder(itemView) {
    val transitionText = itemView.findViewById<TextView>(R.id.item_test_text)
    }
}

in onItemClick I pass the textView form item in recyclerView for transition

transition end

class TransitionEndFragment : Fragment() {

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    setUpTransition()
    return inflater.inflate(R.layout.fragment_transition_end, container, false)
    }

private fun setUpTransition(){
    sharedElementEnterTransition = TransitionInflater.from(context).inflateTransition(android.R.transition.move)

    }
}

layout

<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<TextView
    android:id="@+id/transition_end_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="transition"
    android:transitionName="transitionTextEnd"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

fun transitionWithTextViewInFragment() - has transition.

fun transitionWithTextViewInRecyclerViewItem(view: View) - no transition.

Body:
To solve the return transition problem you need to add this lines on the Source Fragment (the fragment with the recycler view) where you initialize your recycler view

// your recyclerView
recyclerView.apply {
                ...
                adapter = myAdapter
                postponeEnterTransition()
                viewTreeObserver
                    .addOnPreDrawListener {
                        startPostponedEnterTransition()
                        true
                    }
}


问:
Split a string that holds characters in different sizes
I have an input string that holds characters in different sizes, for example const char * input = "aadđ€€¢¢".
The strlen gave result 15, which mean while 'aad' only took 3 bytes, the other special characters took 2 bytes or more each.

How can I cut characters that fit into 6 bytes from the start of that string? Which mean in this case only 'aadđ' will be taken because aadđ€ would occupy 8 bytes.

I tried normal split character methods but none worked so far. Edit: Because a wide character might get split in the middle and therefore I will get some garbage or a different character instead.

答:
Can't understand your problem since you didn't describe the issue you encountered. But this should work. The only problem may be that a wide character might get split in the middle and you can get a different char

```<code>char input2[7] = {0};
memcpy(input2, input, 6);
</code>```

If you want to get the wchar len you can use wcslen()

http://www.cplusplus.com/reference/cwchar/wcslen/

Body:
Can't understand your problem since you didn't describe the issue you encountered. But this should work. The only problem may be that a wide character might get split in the middle and you can get a different char

char input2[7] = {0};
memcpy(input2, input, 6);

If you want to get the wchar len you can use wcslen()

http://www.cplusplus.com/reference/cwchar/wcslen/


问:
Custom Expandable RecyclerView Crashing on notifyItemRangeRemoved and notifyItemRangeInserted
I have created expandable recylerview following is my adapter code

```<code>public class FoodMenuRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    List<Object> objects;
    FoodMenuParentListener foodMenuParentListener;
    boolean isAddAllowed;

    boolean isVegOnly;
    static final int TYPE_FOOD = 0;
    static final int TYPE_MENU_ITEM = 1;

    public FoodMenuRecyclerAdapter(List<Object> objects, FoodMenuParentListener foodMenuParentListener, boolean isVegOnly, boolean isAddAllowed) {
        this.foodMenuParentListener = foodMenuParentListener;
        this.isVegOnly = isVegOnly;
        this.isAddAllowed = isAddAllowed;
        this.objects = objects;
    }

    @Override
    public int getItemViewType(int position) {
        Object object = objects.get(position);
        if (object instanceof FoodMenuItem) {
            return TYPE_FOOD;
        } else if(this.objects.get(position) == null) {
            throw new IllegalStateException("Null object added");
        }else {
            return TYPE_MENU_ITEM;
        }
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View view;
        switch (getItemViewType(i)) {
            case TYPE_FOOD:
                view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.layout_food_parent, viewGroup, false);
                return new MenuViewHolder(view);
            case TYPE_MENU_ITEM:
                view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.layout_food_child, viewGroup, false);
                return new ChildMenuHolder(view);
            default:
                throw new IllegalArgumentException("Invalid viewType");

        }
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
        Object object = objects.get(i);
        Context context = viewHolder.itemView.getContext();
        Log.d("myAdapter","position"+ i + ":"+ ((getItemViewType(i) == TYPE_MENU_ITEM) ? "TYPE_MENU_ITEM" : "TYPE_FOOD"));
         if (getItemViewType(i) == TYPE_MENU_ITEM) {
            ChildMenuHolder childMenuHolder = (ChildMenuHolder) viewHolder;

            Item item = (Item) object;

            childMenuHolder.tvTitle.setText(item.getTitle());
            childMenuHolder.txtQty.setText(String.valueOf(item.getQuatity()));
            childMenuHolder.txtCartInc.setVisibility(item.isAddedToCart() ? View.VISIBLE : View.GONE);
            childMenuHolder.txtQty.setVisibility(item.isAddedToCart() ? View.VISIBLE : View.GONE);
            childMenuHolder.txtCartDec.setVisibility(item.isAddedToCart() ? View.VISIBLE : View.GONE);
            childMenuHolder.btnAdd.setVisibility(!item.isAddedToCart() ? View.VISIBLE : View.GONE);
            childMenuHolder.btnAdd.setBackgroundResource(isAddAllowed ? R.drawable.rounded_bottom_edge_shape_food : R.drawable.rounded_bottom_edge_shape_disable);
            childMenuHolder.btnAdd.setTextColor(isAddAllowed ? ContextCompat.getColor(context, R.color.button_green) : ContextCompat.getColor(context, R.color.gray_a1));
            childMenuHolder.ivType.setColorFilter(item.getType().equalsIgnoreCase(Item.FOOD_TYPE_VEG) ? ContextCompat.getColor(context, R.color.selected_green) : ContextCompat.getColor(context, R.color.app_red));
        } else {
            FoodMenuItem foodMenuItem = (FoodMenuItem) object;
            MenuViewHolder menuViewHolder = (MenuViewHolder) viewHolder;
            if (isVegOnly) {
                List<Item> items = new ArrayList<>();
                for (Item item : foodMenuItem.getItems()) {
                    if (item.getType().equalsIgnoreCase(Item.FOOD_TYPE_VEG)) {
                        items.add(item);
                    }
                }
                menuViewHolder.tvNumItems.setText("(" + items.size() + " items)");

            } else {
                menuViewHolder.tvNumItems.setText("(" + foodMenuItem.getItems().size() + " items)");

            }
            menuViewHolder.ivArrow.setImageResource(foodMenuItem.isExpanded() ? R.drawable.chev_up : R.drawable.chev_down);
            menuViewHolder.tvTitle.setText(foodMenuItem.getCategoryName());
        }

    }

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

    public class MenuViewHolder extends RecyclerView.ViewHolder {
        TextView tvTitle;
        TextView tvNumItems;
        ImageView ivArrow;
        // RecyclerView rvMenu;
        View rlArrow;

        public MenuViewHolder(@NonNull View itemView) {
            super(itemView);
            tvTitle = (TextView) itemView.findViewById(R.id.tvTitle);
            tvNumItems = (TextView) itemView.findViewById(R.id.tvNumItems);
            ivArrow = (ImageView) itemView.findViewById(R.id.ivArrow);
            // rvMenu.setNestedScrollingEnabled(false);
            rlArrow = itemView.findViewById(R.id.rlArrow);
            rlArrow.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (foodMenuParentListener != null) {
                        Object object = objects.get(getAdapterPosition());
                        if (object instanceof FoodMenuItem) {
                            FoodMenuItem foodMenuItem = (FoodMenuItem) object;
                            foodMenuParentListener.OnExpandClick(foodMenuItem, getAdapterPosition());

                        }
                    }
                }
            });
            tvTitle.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (foodMenuParentListener != null) {
                        Object object = objects.get(getAdapterPosition());
                        if (object instanceof FoodMenuItem) {
                            FoodMenuItem foodMenuItem = (FoodMenuItem) object;
                            foodMenuParentListener.OnExpandClick(foodMenuItem, getAdapterPosition());

                        }
                    }
                }
            });
        }
    }

    public boolean isVegOnly() {
        return isVegOnly;
    }

    public void setVegOnly(boolean vegOnly) {
        isVegOnly = vegOnly;
    }

    public interface FoodMenuParentListener extends AddItemListener {
        public void OnExpandClick(FoodMenuItem foodMenuItem, int position);

        public void OnVegOnlyClicked();
    }

    public class ChildMenuHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        ImageView ivType;
        TextView tvTitle;
        TextView tvPrice;
        TextView txtCartDec;
        TextView txtQty;
        TextView txtCartInc;

        Button btnAdd;

        public ChildMenuHolder(@NonNull View itemView) {
            super(itemView);
            ivType = (ImageView) itemView.findViewById(R.id.ivType);
            tvTitle = (TextView) itemView.findViewById(R.id.tvTitle);
            tvPrice = (TextView) itemView.findViewById(R.id.tvPrice);
            txtCartDec = (TextView) itemView.findViewById(R.id.txtCartDec);
            txtQty = (TextView) itemView.findViewById(R.id.txtQty);
            txtCartInc = (TextView) itemView.findViewById(R.id.txtCartInc);
            btnAdd = (Button) itemView.findViewById(R.id.btnAdd);
            btnAdd.setOnClickListener(this);
            txtCartInc.setOnClickListener(this);
            txtCartDec.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {

        }
    }

    public void setExpandIndex(int expandIndex) {
    }

    public boolean isItemExpanded(int position) {
        return true;
    }

    public class VegOnlyViewHolder extends RecyclerView.ViewHolder {
        Switch wtVeg;

        public VegOnlyViewHolder(@NonNull View itemView) {
            super(itemView);
            wtVeg = (Switch) itemView.findViewById(R.id.wtVeg);
            wtVeg.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                    if (foodMenuParentListener != null) {
                        foodMenuParentListener.OnVegOnlyClicked();
                    }
                }
            });
        }
    }

    public interface AddItemListener {
        public void onAddClicked(Item item, int parentIndex);

        public void increaseItemCount(Item item, int parentIndex);

        public void decreaseItemCount(Item item, int parentIndex);
    }

    public void addAll(int position, List<Item> objectsToAdd) {
        this.objects.addAll(position, objectsToAdd);
    }

    public void addItem(int position, Item object) {
        this.objects.add(position, object);
    }
    public void removeItem(Object object) {
        this.objects.remove(object);
    }

    public void removeAll(List<Item> objectsToRemove) {
        objects.removeAll(objectsToRemove);
        Log.d("myAdapter","item at first position after remove" + ":"+objects.get(0));
        Log.d("myAdapter","item at second position after remove" + ":"+objects.get(1));
    }

    public Object isItemInList(Item item) {
        for (Object object : objects) {
            if (object instanceof Item && ((Item) object).getId().equals(item.getId())) {
                return object;
            }
        }
        return null;
    }
    }
</code>```

Following is code in my Fragment to expand collapse RecyclerView

```<code> @Override
        public void OnExpandClick(FoodMenuItem foodMenuItem, int position) {
            if (recyclerViewMenu != null && recyclerViewMenu.getAdapter() != null) {
                recyclerViewMenu.getRecycledViewPool().clear();
                FoodMenuRecyclerAdapter foodMenuRecyclerAdapter = (FoodMenuRecyclerAdapter) recyclerViewMenu.getAdapter();
                foodMenuItem.setExpanded(!foodMenuItem.isExpanded());
                if (foodMenuItem.isExpanded()) {
                    foodMenuRecyclerAdapter.addAll(position + 1, foodMenuItem.getItems());
                    foodMenuRecyclerAdapter.notifyItemRangeInserted(position, foodMenuItem.getItems().size());

                } else {
                    foodMenuRecyclerAdapter.removeAll(foodMenuItem.getItems());
                    foodMenuRecyclerAdapter.notifyItemRangeRemoved(position + 1, foodMenuItem.getItems().size());

                }

            }

        }
</code>```

Following is listener code inside fragment to expand and collapse

```<code>public void OnExpandClick(FoodMenuItem foodMenuItem, int position) {
            if (recyclerViewMenu != null && recyclerViewMenu.getAdapter() != null) {
                FoodMenuRecyclerAdapter foodMenuRecyclerAdapter = (FoodMenuRecyclerAdapter) recyclerViewMenu.getAdapter();
                foodMenuItem.setExpanded(!foodMenuItem.isExpanded());
                if (foodMenuItem.isExpanded()) {
                    foodMenuRecyclerAdapter.addAll(position + 1, foodMenuItem.getItems());
                    foodMenuRecyclerAdapter.notifyItemRangeInserted(position, foodMenuItem.getItems().size());

                } else {
                    foodMenuRecyclerAdapter.removeAll(foodMenuItem.getItems());
                    foodMenuRecyclerAdapter.notifyItemRangeRemoved(position +1 , foodMenuItem.getItems().size());

                }

            }

        }
</code>```

Above code is throwing exception following is exception stack trace

```<code> java.lang.ClassCastException: com.myapp.android.pojoentities.Item cannot be cast to com.myapp.android.pojoentities.FoodMenuItem
    at com.myapp.android.food.menu.FoodMenuRecyclerAdapter.onBindViewHolder(FoodMenuRecyclerAdapter.java:104)
    at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:6781)
    at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:6823)
    at android.support.v7.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5752)
    at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6019)
    at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5858)
    at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5854)
    at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2230)
    at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1557)
    at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1517)
    at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:612)
    at android.support.v7.widget.RecyclerView.dispatchLayoutStep1(RecyclerView.java:3875)
    at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3639)
    at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:4194)
    at android.view.View.layout(View.java:16636)
    at android.view.ViewGroup.layout(ViewGroup.java:5437)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:273)
    at android.view.View.layout(View.java:16636)
    at android.view.ViewGroup.layout(ViewGroup.java:5437)
    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743)
    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586)
    at android.widget.LinearLayout.onLayout(LinearLayout.java:1495)
    at android.view.View.layout(View.java:16636)
    at android.view.ViewGroup.layout(ViewGroup.java:5437)
    at android.support.design.widget.CoordinatorLayout.layoutChild(CoordinatorLayout.java:1183)
    at android.support.design.widget.CoordinatorLayout.onLayoutChild(CoordinatorLayout.java:870)
    at android.support.design.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:889)
    at android.view.View.layout(View.java:16636)
    at android.view.ViewGroup.layout(ViewGroup.java:5437)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:273)
    at com.myapp.android.custom.FitsSystemWindowsFrameLayout.onLayout(FitsSystemWindowsFrameLayout.java:247)
    at android.view.View.layout(View.java:16636)
    at android.view.ViewGroup.layout(ViewGroup.java:5437)
    at android.support.v4.widget.DrawerLayout.onLayout(DrawerLayout.java:1231)
    at android.view.View.layout(View.java:16636)
    at android.view.ViewGroup.layout(ViewGroup.java:5437)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:273)
    at android.view.View.layout(View.java:16636)
    at android.view.ViewGroup.layout(ViewGroup.java:5437)
    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743)
    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586)
    at android.widget.LinearLayout.onLayout(LinearLayout.java:1495)
    at android.view.View.layout(View.java:16636)
    at android.view.ViewGroup.layout(ViewGroup.java:5437)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:273)
    at android.view.View.layout(View.java:16636)
    at android.view.ViewGroup.layout(ViewGroup.java:5437)
    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743)
    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586)
    at android.widget.LinearLayout.onLayout(LinearLayout.java:1495)
    at android.view.View.layout(View.java:
</code>```

Update:

After collapsing first item I have checked log for type of first two items in list found that first two items are of type ParentItem which is FoodMenuItem but when I checked log for getItemViewType for same positions it is returning wrong value somehow

Following are logs

```<code>05-28 00:13:47.643 32010-32010/com.myapp.android D/myAdapter: item at first position after remove:com.myapp.android.pojoentities.FoodMenuItem@7fdf002
05-28 00:13:47.643 32010-32010/com.myapp.android D/myAdapter: item at second position after remove:com.myapp.android.pojoentities.FoodMenuItem@9cbfd13
05-28 00:13:47.664 32010-32010/com.myapp.android D/myAdapter: position1:TYPE_FOOD
05-28 00:13:47.678 32010-32010/com.myapp.android D/myAdapter: position2:TYPE_MENU_ITEM
</code>```

here is sample project for reference

答:
This is not directly the solution of the question asked but the result is same with safer code flow

Steps:

You can make a List List<MyDataType> myList = new ArrayList<>(); to store or change your data to be displayed.

Now if you want your recyclerView to be blank clean the list, then create a new Adapter Class object and set your recylerView with the new adapter object

myList.clear()
MyRecAdapter newEmptyRecAdapter = new MyRecAdapter(myList);
recyclerView.setAdapter(newEmptyRecAdapter);

Again fill the List from your Model or POJO or where your data is saved or fetched and create a new recyclerView Object and reset to the adapter

myList = myModelClass.getList();
MyRecAdapter newFullRecAdapter = new MyRecAdapter(myEmptyList);
recyclerView.setAdapter(newFullRecAdapter);

UPDATED

As per comment:

does not solve my problem getting issue on expand and collpase looking
  answer around it

Steps:

Make a Model or POJO and fetch your recyler data directly from that Model/POJO

Clear the Model/POJO with 0 data filling

run recyclerView.notifyDatasetChanged() this shall automatically collapse the recyclerView

provide a time gap and refill the Model/POJO and recall recyclerView.notifyDatasetChanged()

Body:
I have created expandable recylerview following is my adapter code

public class FoodMenuRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    List<Object> objects;
    FoodMenuParentListener foodMenuParentListener;
    boolean isAddAllowed;

    boolean isVegOnly;
    static final int TYPE_FOOD = 0;
    static final int TYPE_MENU_ITEM = 1;

    public FoodMenuRecyclerAdapter(List<Object> objects, FoodMenuParentListener foodMenuParentListener, boolean isVegOnly, boolean isAddAllowed) {
        this.foodMenuParentListener = foodMenuParentListener;
        this.isVegOnly = isVegOnly;
        this.isAddAllowed = isAddAllowed;
        this.objects = objects;
    }

    @Override
    public int getItemViewType(int position) {
        Object object = objects.get(position);
        if (object instanceof FoodMenuItem) {
            return TYPE_FOOD;
        } else if(this.objects.get(position) == null) {
            throw new IllegalStateException("Null object added");
        }else {
            return TYPE_MENU_ITEM;
        }
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View view;
        switch (getItemViewType(i)) {
            case TYPE_FOOD:
                view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.layout_food_parent, viewGroup, false);
                return new MenuViewHolder(view);
            case TYPE_MENU_ITEM:
                view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.layout_food_child, viewGroup, false);
                return new ChildMenuHolder(view);
            default:
                throw new IllegalArgumentException("Invalid viewType");

        }
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
        Object object = objects.get(i);
        Context context = viewHolder.itemView.getContext();
        Log.d("myAdapter","position"+ i + ":"+ ((getItemViewType(i) == TYPE_MENU_ITEM) ? "TYPE_MENU_ITEM" : "TYPE_FOOD"));
         if (getItemViewType(i) == TYPE_MENU_ITEM) {
            ChildMenuHolder childMenuHolder = (ChildMenuHolder) viewHolder;

            Item item = (Item) object;

            childMenuHolder.tvTitle.setText(item.getTitle());
            childMenuHolder.txtQty.setText(String.valueOf(item.getQuatity()));
            childMenuHolder.txtCartInc.setVisibility(item.isAddedToCart() ? View.VISIBLE : View.GONE);
            childMenuHolder.txtQty.setVisibility(item.isAddedToCart() ? View.VISIBLE : View.GONE);
            childMenuHolder.txtCartDec.setVisibility(item.isAddedToCart() ? View.VISIBLE : View.GONE);
            childMenuHolder.btnAdd.setVisibility(!item.isAddedToCart() ? View.VISIBLE : View.GONE);
            childMenuHolder.btnAdd.setBackgroundResource(isAddAllowed ? R.drawable.rounded_bottom_edge_shape_food : R.drawable.rounded_bottom_edge_shape_disable);
            childMenuHolder.btnAdd.setTextColor(isAddAllowed ? ContextCompat.getColor(context, R.color.button_green) : ContextCompat.getColor(context, R.color.gray_a1));
            childMenuHolder.ivType.setColorFilter(item.getType().equalsIgnoreCase(Item.FOOD_TYPE_VEG) ? ContextCompat.getColor(context, R.color.selected_green) : ContextCompat.getColor(context, R.color.app_red));
        } else {
            FoodMenuItem foodMenuItem = (FoodMenuItem) object;
            MenuViewHolder menuViewHolder = (MenuViewHolder) viewHolder;
            if (isVegOnly) {
                List<Item> items = new ArrayList<>();
                for (Item item : foodMenuItem.getItems()) {
                    if (item.getType().equalsIgnoreCase(Item.FOOD_TYPE_VEG)) {
                        items.add(item);
                    }
                }
                menuViewHolder.tvNumItems.setText("(" + items.size() + " items)");

            } else {
                menuViewHolder.tvNumItems.setText("(" + foodMenuItem.getItems().size() + " items)");

            }
            menuViewHolder.ivArrow.setImageResource(foodMenuItem.isExpanded() ? R.drawable.chev_up : R.drawable.chev_down);
            menuViewHolder.tvTitle.setText(foodMenuItem.getCategoryName());
        }

    }

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

    public class MenuViewHolder extends RecyclerView.ViewHolder {
        TextView tvTitle;
        TextView tvNumItems;
        ImageView ivArrow;
        // RecyclerView rvMenu;
        View rlArrow;

        public MenuViewHolder(@NonNull View itemView) {
            super(itemView);
            tvTitle = (TextView) itemView.findViewById(R.id.tvTitle);
            tvNumItems = (TextView) itemView.findViewById(R.id.tvNumItems);
            ivArrow = (ImageView) itemView.findViewById(R.id.ivArrow);
            // rvMenu.setNestedScrollingEnabled(false);
            rlArrow = itemView.findViewById(R.id.rlArrow);
            rlArrow.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (foodMenuParentListener != null) {
                        Object object = objects.get(getAdapterPosition());
                        if (object instanceof FoodMenuItem) {
                            FoodMenuItem foodMenuItem = (FoodMenuItem) object;
                            foodMenuParentListener.OnExpandClick(foodMenuItem, getAdapterPosition());

                        }
                    }
                }
            });
            tvTitle.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (foodMenuParentListener != null) {
                        Object object = objects.get(getAdapterPosition());
                        if (object instanceof FoodMenuItem) {
                            FoodMenuItem foodMenuItem = (FoodMenuItem) object;
                            foodMenuParentListener.OnExpandClick(foodMenuItem, getAdapterPosition());

                        }
                    }
                }
            });
        }
    }

    public boolean isVegOnly() {
        return isVegOnly;
    }

    public void setVegOnly(boolean vegOnly) {
        isVegOnly = vegOnly;
    }

    public interface FoodMenuParentListener extends AddItemListener {
        public void OnExpandClick(FoodMenuItem foodMenuItem, int position);

        public void OnVegOnlyClicked();
    }

    public class ChildMenuHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        ImageView ivType;
        TextView tvTitle;
        TextView tvPrice;
        TextView txtCartDec;
        TextView txtQty;
        TextView txtCartInc;

        Button btnAdd;

        public ChildMenuHolder(@NonNull View itemView) {
            super(itemView);
            ivType = (ImageView) itemView.findViewById(R.id.ivType);
            tvTitle = (TextView) itemView.findViewById(R.id.tvTitle);
            tvPrice = (TextView) itemView.findViewById(R.id.tvPrice);
            txtCartDec = (TextView) itemView.findViewById(R.id.txtCartDec);
            txtQty = (TextView) itemView.findViewById(R.id.txtQty);
            txtCartInc = (TextView) itemView.findViewById(R.id.txtCartInc);
            btnAdd = (Button) itemView.findViewById(R.id.btnAdd);
            btnAdd.setOnClickListener(this);
            txtCartInc.setOnClickListener(this);
            txtCartDec.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {

        }
    }

    public void setExpandIndex(int expandIndex) {
    }

    public boolean isItemExpanded(int position) {
        return true;
    }

    public class VegOnlyViewHolder extends RecyclerView.ViewHolder {
        Switch wtVeg;

        public VegOnlyViewHolder(@NonNull View itemView) {
            super(itemView);
            wtVeg = (Switch) itemView.findViewById(R.id.wtVeg);
            wtVeg.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                    if (foodMenuParentListener != null) {
                        foodMenuParentListener.OnVegOnlyClicked();
                    }
                }
            });
        }
    }

    public interface AddItemListener {
        public void onAddClicked(Item item, int parentIndex);

        public void increaseItemCount(Item item, int parentIndex);

        public void decreaseItemCount(Item item, int parentIndex);
    }

    public void addAll(int position, List<Item> objectsToAdd) {
        this.objects.addAll(position, objectsToAdd);
    }

    public void addItem(int position, Item object) {
        this.objects.add(position, object);
    }
    public void removeItem(Object object) {
        this.objects.remove(object);
    }

    public void removeAll(List<Item> objectsToRemove) {
        objects.removeAll(objectsToRemove);
        Log.d("myAdapter","item at first position after remove" + ":"+objects.get(0));
        Log.d("myAdapter","item at second position after remove" + ":"+objects.get(1));
    }

    public Object isItemInList(Item item) {
        for (Object object : objects) {
            if (object instanceof Item && ((Item) object).getId().equals(item.getId())) {
                return object;
            }
        }
        return null;
    }
    }

Following is code in my Fragment to expand collapse RecyclerView

 @Override
        public void OnExpandClick(FoodMenuItem foodMenuItem, int position) {
            if (recyclerViewMenu != null && recyclerViewMenu.getAdapter() != null) {
                recyclerViewMenu.getRecycledViewPool().clear();
                FoodMenuRecyclerAdapter foodMenuRecyclerAdapter = (FoodMenuRecyclerAdapter) recyclerViewMenu.getAdapter();
                foodMenuItem.setExpanded(!foodMenuItem.isExpanded());
                if (foodMenuItem.isExpanded()) {
                    foodMenuRecyclerAdapter.addAll(position + 1, foodMenuItem.getItems());
                    foodMenuRecyclerAdapter.notifyItemRangeInserted(position, foodMenuItem.getItems().size());

                } else {
                    foodMenuRecyclerAdapter.removeAll(foodMenuItem.getItems());
                    foodMenuRecyclerAdapter.notifyItemRangeRemoved(position + 1, foodMenuItem.getItems().size());

                }

            }

        }

Following is listener code inside fragment to expand and collapse

public void OnExpandClick(FoodMenuItem foodMenuItem, int position) {
            if (recyclerViewMenu != null && recyclerViewMenu.getAdapter() != null) {
                FoodMenuRecyclerAdapter foodMenuRecyclerAdapter = (FoodMenuRecyclerAdapter) recyclerViewMenu.getAdapter();
                foodMenuItem.setExpanded(!foodMenuItem.isExpanded());
                if (foodMenuItem.isExpanded()) {
                    foodMenuRecyclerAdapter.addAll(position + 1, foodMenuItem.getItems());
                    foodMenuRecyclerAdapter.notifyItemRangeInserted(position, foodMenuItem.getItems().size());

                } else {
                    foodMenuRecyclerAdapter.removeAll(foodMenuItem.getItems());
                    foodMenuRecyclerAdapter.notifyItemRangeRemoved(position +1 , foodMenuItem.getItems().size());

                }

            }

        }

Above code is throwing exception following is exception stack trace

 java.lang.ClassCastException: com.myapp.android.pojoentities.Item cannot be cast to com.myapp.android.pojoentities.FoodMenuItem
    at com.myapp.android.food.menu.FoodMenuRecyclerAdapter.onBindViewHolder(FoodMenuRecyclerAdapter.java:104)
    at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:6781)
    at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:6823)
    at android.support.v7.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5752)
    at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6019)
    at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5858)
    at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5854)
    at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2230)
    at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1557)
    at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1517)
    at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:612)
    at android.support.v7.widget.RecyclerView.dispatchLayoutStep1(RecyclerView.java:3875)
    at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3639)
    at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:4194)
    at android.view.View.layout(View.java:16636)
    at android.view.ViewGroup.layout(ViewGroup.java:5437)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:273)
    at android.view.View.layout(View.java:16636)
    at android.view.ViewGroup.layout(ViewGroup.java:5437)
    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743)
    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586)
    at android.widget.LinearLayout.onLayout(LinearLayout.java:1495)
    at android.view.View.layout(View.java:16636)
    at android.view.ViewGroup.layout(ViewGroup.java:5437)
    at android.support.design.widget.CoordinatorLayout.layoutChild(CoordinatorLayout.java:1183)
    at android.support.design.widget.CoordinatorLayout.onLayoutChild(CoordinatorLayout.java:870)
    at android.support.design.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:889)
    at android.view.View.layout(View.java:16636)
    at android.view.ViewGroup.layout(ViewGroup.java:5437)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:273)
    at com.myapp.android.custom.FitsSystemWindowsFrameLayout.onLayout(FitsSystemWindowsFrameLayout.java:247)
    at android.view.View.layout(View.java:16636)
    at android.view.ViewGroup.layout(ViewGroup.java:5437)
    at android.support.v4.widget.DrawerLayout.onLayout(DrawerLayout.java:1231)
    at android.view.View.layout(View.java:16636)
    at android.view.ViewGroup.layout(ViewGroup.java:5437)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:273)
    at android.view.View.layout(View.java:16636)
    at android.view.ViewGroup.layout(ViewGroup.java:5437)
    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743)
    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586)
    at android.widget.LinearLayout.onLayout(LinearLayout.java:1495)
    at android.view.View.layout(View.java:16636)
    at android.view.ViewGroup.layout(ViewGroup.java:5437)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:273)
    at android.view.View.layout(View.java:16636)
    at android.view.ViewGroup.layout(ViewGroup.java:5437)
    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743)
    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586)
    at android.widget.LinearLayout.onLayout(LinearLayout.java:1495)
    at android.view.View.layout(View.java:

Update:

After collapsing first item I have checked log for type of first two items in list found that first two items are of type ParentItem which is FoodMenuItem but when I checked log for getItemViewType for same positions it is returning wrong value somehow

Following are logs

05-28 00:13:47.643 32010-32010/com.myapp.android D/myAdapter: item at first position after remove:com.myapp.android.pojoentities.FoodMenuItem@7fdf002
05-28 00:13:47.643 32010-32010/com.myapp.android D/myAdapter: item at second position after remove:com.myapp.android.pojoentities.FoodMenuItem@9cbfd13
05-28 00:13:47.664 32010-32010/com.myapp.android D/myAdapter: position1:TYPE_FOOD
05-28 00:13:47.678 32010-32010/com.myapp.android D/myAdapter: position2:TYPE_MENU_ITEM

here is sample project for reference


问:
ionic tabs icons dynamic color
I want to change the icons color of tabs based on a hex variable changed from the api

I've tried to use [ngStyle] and [ngClass] elements and play with them but nothing seems to help

```<code>  <ion-tab [root]="tab1Root" tabTitle="{{homeTitle}}" tabIcon="home"></ion-tab>
  <ion-tab [root]="tab2Root" tabTitle="{{searchTitle}}" tabIcon="search"></ion-tab>
  <ion-tab [root]="tab4Root"  tabIcon="options" ></ion-tab>
</ion-tabs>

<ion-tabs *ngIf="showKpi">
  <ion-tab [root]="tab1Root" tabTitle="{{homeTitle}}" tabIcon="home"></ion-tab>
  <ion-tab [root]="tab3Root" tabTitle="{{kpiTitle}}" tabIcon="stats" ></ion-tab>
  <ion-tab [root]="tab2Root" tabTitle="{{searchTitle}}" tabIcon="search"></ion-tab>
  <ion-tab [root]="tab4Root"  tabIcon="options" ></ion-tab>
```</ion-tabs>

I was able to change the background dynamically
```

答:
Try:

```<code>[style.color]="myColor"
</code>```

Or

```<code>[style.backgroundColor]="myColor"
</code>```

And the value of color from the API:

```<code>this.myColor = 'valueFromAPI'
</code>```

Title: ionic tabs icons dynamic color

Body:
I want to change the icons color of tabs based on a hex variable changed from the api

I've tried to use [ngStyle] and [ngClass] elements and play with them but nothing seems to help

  <ion-tab [root]="tab1Root" tabTitle="{{homeTitle}}" tabIcon="home"></ion-tab>
  <ion-tab [root]="tab2Root" tabTitle="{{searchTitle}}" tabIcon="search"></ion-tab>
  <ion-tab [root]="tab4Root"  tabIcon="options" ></ion-tab>
</ion-tabs>

<ion-tabs *ngIf="showKpi">
  <ion-tab [root]="tab1Root" tabTitle="{{homeTitle}}" tabIcon="home"></ion-tab>
  <ion-tab [root]="tab3Root" tabTitle="{{kpiTitle}}" tabIcon="stats" ></ion-tab>
  <ion-tab [root]="tab2Root" tabTitle="{{searchTitle}}" tabIcon="search"></ion-tab>
  <ion-tab [root]="tab4Root"  tabIcon="options" ></ion-tab>
```</ion-tabs>

I was able to change the background dynamically

Body:
Try:

[style.color]="myColor"

Or

[style.backgroundColor]="myColor"

And the value of color from the API:

this.myColor = 'valueFromAPI'


问:
AWS S3 check if file exists based on a conditional path
I would like to check if a file exists in a separate directory of the bucket if a given file exists. I have the following directory structure-

```<code>import boto3
s3 = boto3.resource('s3')
def file_exists(fileN):
    try:
        s3.Object('my-bucket', 'folder1/folder2/'+fileN).load()
    except:
        return False
    else:
        fileN = fileN.split(".")[0]
        try:

            s3.Object('my-bucket', 'folder1/<randomid folderxxxx>/'+fileN+'_condition.jpg').load()
        except:
            return False
        else:
            return True

file_exists("test.jpg")
</code>```

This works but as long as I can send the randomfolderIDas an argument. Is there a better and elegant way to do it?

Basically I have to check if,

my-bucket/folder1/folder2/test.jpg if this exists then check
my-bucket/folder1/<randomID>/test_condition.jpg if this also exists then return True

答:
It is not possible to specify an object key via a wildcard.

Instead, you would need to do a bucket listing (which can be against the whole bucket, or within a path) and then perform your own logic for identifying the file of interest.

If the number of objects is small (eg a few thousand), the list can be easily retrieved and kept in memory for fast comparison in a Python list.

If there are millions of objects, you might consider using Amazon S3 Inventory, which can provide a daily CSV file that lists all objects in the bucket. Using such a file would be faster than scanning the bucket itself.

Body:
I would like to check if a file exists in a separate directory of the bucket if a given file exists. I have the following directory structure-

import boto3
s3 = boto3.resource('s3')
def file_exists(fileN):
    try:
        s3.Object('my-bucket', 'folder1/folder2/'+fileN).load()
    except:
        return False
    else:
        fileN = fileN.split(".")[0]
        try:

            s3.Object('my-bucket', 'folder1/<randomid folderxxxx>/'+fileN+'_condition.jpg').load()
        except:
            return False
        else:
            return True

file_exists("test.jpg")

This works but as long as I can send the randomfolderIDas an argument. Is there a better and elegant way to do it?

Basically I have to check if,

my-bucket/folder1/folder2/test.jpg if this exists then check
my-bucket/folder1/<randomID>/test_condition.jpg if this also exists then return True