问:
Multiple widgets used the same globalkey error in flutter
I tried to solve this, I looked up the answers in Stack Overflow

But I haven't solved it yet

I used the global key in the create and update pages

What I've done

I tried adding static to the global key ,but I couldn't
because I couldn't wrap the key in a refreshIndicator.

I used Navigator pushNamed instead of Navigator push

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

class Update extends StatefulWidget {
  @override
  _UpdateState createState() => _UpdateState();
}

class _UpdateState extends State<Update> {
  GlobalKey<FormState> _formKey1 = GlobalKey<FormState>(debugLabel: '_updateFormKey');

  TextEditingController _titleController1 = TextEditingController();
  TextEditingController _descController1 = TextEditingController();
  final db = Firestore.instance;
  DocumentSnapshot _currentDocument;

  @override
  Widget build(BuildContext context) {
    final Size size = MediaQuery.of(context).size;

    return MaterialApp(
        home: Scaffold(
            resizeToAvoidBottomInset: false,
            appBar: AppBar(
              title: Text('update'),
            ),
            body: _buildUpdate(context)));
  }

  Widget _buildUpdate(BuildContext context) {
    final Size size = MediaQuery.of(context).size;

    return StreamBuilder<QuerySnapshot>(
      stream: db.collection('flutter_data2').snapshots(),
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return Column(
            children: snapshot.data.documents.map<Widget>((doc) {
              return Column(
                children: <Widget>[
                  Padding(
                    padding: EdgeInsets.all(20.0),
                    child: Card(
                      elevation: 2.0,
                      shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(16.0)),
                      child: Form(
                        key: _formKey1,
                        child: Padding(
                          padding: EdgeInsets.only(left: 12, right: 12),
                          child: Column(
                            children: <Widget>[
                              TextFormField(
                                controller: _titleController1,
                                decoration: InputDecoration(labelText: doc.data['title']),
                                validator: (String value) {
                                  if (value.isEmpty) {
                                    return 'title empty';
                                  } else {
                                    return null;
                                  }
                                },
                              ),
                              TextFormField(
                                controller: _descController1,
                                decoration: InputDecoration(labelText: doc.data['desc']),
                                validator: (String value) {
                                  if (value.isEmpty) {
                                    return 'desc empty';
                                  } else {
                                    return null;
                                  }
                                },
                              ),
                            ],
                          ),
                        ),
                      ),
                    ),
                  ),
                  RaisedButton(
                    shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(15.0)),
                    child: Text('update'),
                    color: Colors.blue,
                    onPressed: () async {
                      if (_formKey1.currentState.validate()) {
                        db
                            .collection('flutter_data2')
                            .document(doc.documentID)
                            .updateData({'title': _titleController1.text,'desc':_descController1.text});
                        Navigator.pop(context);
                      }
                    },
                  ),
                ],
              );
            }).toList(),
          );
        } else {
          return SizedBox();
        }
      },
    );
  }
}
</code>```

答:
You might really want to use some modularity here. Create your custom Form widget preferably in a different file with their own set of controllers. This way you won't have to manage the controllers explicitly. One more thing to notice is that your Button is doing the same job for every entry. In this case, you might as well add the global key inside your custom Form widget and hardcode the onPressed function there.

Here is an example

```<code>// This is a mock data. Your firebase snapshot.data will have a similar structure
List<Map<String, dynamic>> _mockData = [
  {
    'title':'Title 1',
    'desc':'Description 1',
  },
  {
    'title':'Title 2',
    'desc':'Description 2',
  },
  {
    'title':'Title 3',
    'desc':'Description 3',
  },
  {
    'title':'Title 4',
    'desc':'Description 4',
  },
];

// There are many ways to make this work.
// Instead of hardcoding the function in our custom form widget, We would like to pass a function implementation which will be called after the button in the form is pressed. This way we will have more control on what will happen when we press the button
typedef onFormData = Future<void> Function(String, String); // Future void to allow async updates // The two strings are title and description respectively.

// This is the custom form widget you need to create
class MyForm extends StatefulWidget {
  final Map<String, dynamic> data; // Replace it with DocumentSnapshot data.
  final onFormData onPressed; // We will use the type we defined up there. So we will be expecting a function implementation here which takes two strings, a title and a description

  MyForm({@required this.data, @required this.onPressed, Key key}):super(key: key);

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

// Our custom form widget is defined here
class _MyFormState extends State<MyForm> {

  // Define the controllers
  TextEditingController _titleController;
  TextEditingController _descController;

  // Create the key
  GlobalKey<FormState> _formKey;

  @override
  void initState() {
    // Initialize the values here
    super.initState();
    _titleController = TextEditingController();
    _descController = TextEditingController();
    _formKey = GlobalKey<FormState>();
  }

  @override
  void dispose() {
    // Remember that you have to dispose of the controllers once the widget is ready to be disposed of
    _titleController.dispose();
    _descController.dispose();
    _formKey = null;
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // Everything remains almost same here as in your code
    return Column(
      children: <Widget>[
        Padding(
          padding: EdgeInsets.all(20.0),
          child: Card(
            elevation: 2.0,
            shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(16.0)),
            child: Form(
              key: _formKey,
              child: Padding(
                padding: EdgeInsets.only(left: 12, right: 12),
                child: Column(
                  children: <Widget>[
                    TextFormField(
                      controller: _titleController, // Assign the controller
                      decoration:
                          InputDecoration(labelText: widget.data['title']), // widget.data can still be indexed like this after you replace datatype of the data to DocumentSnapshot
                      validator: (String value) {
                        if (value.isEmpty) {
                          return 'title is empty';
                        } else {
                          return null;
                        }
                      },
                    ),
                    TextFormField(
                      controller: _descController,
                      decoration:
                          InputDecoration(labelText: widget.data['desc']), // Same goes here
                      validator: (String value) {
                        if (value.isEmpty) {
                          return 'description is empty';
                        } else {
                          return null;
                        }
                      },
                    ),
                  ],
                ),
              ),
            ),
          ),
        ),
        // The button associated with this form
        RaisedButton(
          shape:
              RoundedRectangleBorder(borderRadius: BorderRadius.circular(15.0)),
          child: Text('Update'),
          color: Colors.blue,
          onPressed: () async {
            // If validation is successful, then call the on pressed function we assigned to the widget. // Check the MyWidget class
            if (_formKey.currentState.validate()) {
              await widget.onPressed(_titleController.text, _descController.text); // Instead of putting firebase update code here, we are passing the title and description to our main widget from where we will post
            }
          },
        ),
      ],
    );
  }
}

// Our main widget
class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Demo'),
      ),
      // Wrap this up in your stream builder
      // I am using a listview with mock data for the sake of this example.
      body: ListView.builder(
      itemBuilder: (context, index) {
        // We create a new instance of our custom form and we don't need to manage any controllers or keys. We just need to pass the data and what happens when we press the update button in our custom form.
        // Here is why we defined a type named onFormData before.
        // You can simply post updates in your form widget directly if your logic is same for each form
        // We are getting the title and description info here through our custom defined Forms without managing any keys and controllers.
        // Also this method is async so you can post your firebase updates from here waiting for them to complete using await
        return MyForm(data: _mockData[index], onPressed: (String title, String description) async {
          // Put your firebase update code here
          _mockData[index]['title'] = title;
          _mockData[index]['desc'] = description;
          Navigator.of(context).pop(); // Go back after the updates are made as written in your example
        });
      },
      physics: BouncingScrollPhysics(),
      itemCount: _mockData.length, // Length of the data.
        ),
    );
  }
}
</code>```

Before any updates:

After writing your title and description:

After pressing update, when you go back to the same screen:

Hope this helps!

Body:
I tried to solve this, I looked up the answers in Stack Overflow

But I haven't solved it yet

I used the global key in the create and update pages

What I've done

I tried adding static to the global key ,but I couldn't
because I couldn't wrap the key in a refreshIndicator.

I used Navigator pushNamed instead of Navigator push

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';

class Update extends StatefulWidget {
  @override
  _UpdateState createState() => _UpdateState();
}

class _UpdateState extends State<Update> {
  GlobalKey<FormState> _formKey1 = GlobalKey<FormState>(debugLabel: '_updateFormKey');

  TextEditingController _titleController1 = TextEditingController();
  TextEditingController _descController1 = TextEditingController();
  final db = Firestore.instance;
  DocumentSnapshot _currentDocument;

  @override
  Widget build(BuildContext context) {
    final Size size = MediaQuery.of(context).size;

    return MaterialApp(
        home: Scaffold(
            resizeToAvoidBottomInset: false,
            appBar: AppBar(
              title: Text('update'),
            ),
            body: _buildUpdate(context)));
  }

  Widget _buildUpdate(BuildContext context) {
    final Size size = MediaQuery.of(context).size;

    return StreamBuilder<QuerySnapshot>(
      stream: db.collection('flutter_data2').snapshots(),
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return Column(
            children: snapshot.data.documents.map<Widget>((doc) {
              return Column(
                children: <Widget>[
                  Padding(
                    padding: EdgeInsets.all(20.0),
                    child: Card(
                      elevation: 2.0,
                      shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(16.0)),
                      child: Form(
                        key: _formKey1,
                        child: Padding(
                          padding: EdgeInsets.only(left: 12, right: 12),
                          child: Column(
                            children: <Widget>[
                              TextFormField(
                                controller: _titleController1,
                                decoration: InputDecoration(labelText: doc.data['title']),
                                validator: (String value) {
                                  if (value.isEmpty) {
                                    return 'title empty';
                                  } else {
                                    return null;
                                  }
                                },
                              ),
                              TextFormField(
                                controller: _descController1,
                                decoration: InputDecoration(labelText: doc.data['desc']),
                                validator: (String value) {
                                  if (value.isEmpty) {
                                    return 'desc empty';
                                  } else {
                                    return null;
                                  }
                                },
                              ),
                            ],
                          ),
                        ),
                      ),
                    ),
                  ),
                  RaisedButton(
                    shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(15.0)),
                    child: Text('update'),
                    color: Colors.blue,
                    onPressed: () async {
                      if (_formKey1.currentState.validate()) {
                        db
                            .collection('flutter_data2')
                            .document(doc.documentID)
                            .updateData({'title': _titleController1.text,'desc':_descController1.text});
                        Navigator.pop(context);
                      }
                    },
                  ),
                ],
              );
            }).toList(),
          );
        } else {
          return SizedBox();
        }
      },
    );
  }
}

Body:
You might really want to use some modularity here. Create your custom Form widget preferably in a different file with their own set of controllers. This way you won't have to manage the controllers explicitly. One more thing to notice is that your Button is doing the same job for every entry. In this case, you might as well add the global key inside your custom Form widget and hardcode the onPressed function there.

Here is an example

// This is a mock data. Your firebase snapshot.data will have a similar structure
List<Map<String, dynamic>> _mockData = [
  {
    'title':'Title 1',
    'desc':'Description 1',
  },
  {
    'title':'Title 2',
    'desc':'Description 2',
  },
  {
    'title':'Title 3',
    'desc':'Description 3',
  },
  {
    'title':'Title 4',
    'desc':'Description 4',
  },
];

// There are many ways to make this work.
// Instead of hardcoding the function in our custom form widget, We would like to pass a function implementation which will be called after the button in the form is pressed. This way we will have more control on what will happen when we press the button
typedef onFormData = Future<void> Function(String, String); // Future void to allow async updates // The two strings are title and description respectively.

// This is the custom form widget you need to create
class MyForm extends StatefulWidget {
  final Map<String, dynamic> data; // Replace it with DocumentSnapshot data.
  final onFormData onPressed; // We will use the type we defined up there. So we will be expecting a function implementation here which takes two strings, a title and a description

  MyForm({@required this.data, @required this.onPressed, Key key}):super(key: key);

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

// Our custom form widget is defined here
class _MyFormState extends State<MyForm> {

  // Define the controllers
  TextEditingController _titleController;
  TextEditingController _descController;

  // Create the key
  GlobalKey<FormState> _formKey;

  @override
  void initState() {
    // Initialize the values here
    super.initState();
    _titleController = TextEditingController();
    _descController = TextEditingController();
    _formKey = GlobalKey<FormState>();
  }

  @override
  void dispose() {
    // Remember that you have to dispose of the controllers once the widget is ready to be disposed of
    _titleController.dispose();
    _descController.dispose();
    _formKey = null;
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // Everything remains almost same here as in your code
    return Column(
      children: <Widget>[
        Padding(
          padding: EdgeInsets.all(20.0),
          child: Card(
            elevation: 2.0,
            shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(16.0)),
            child: Form(
              key: _formKey,
              child: Padding(
                padding: EdgeInsets.only(left: 12, right: 12),
                child: Column(
                  children: <Widget>[
                    TextFormField(
                      controller: _titleController, // Assign the controller
                      decoration:
                          InputDecoration(labelText: widget.data['title']), // widget.data can still be indexed like this after you replace datatype of the data to DocumentSnapshot
                      validator: (String value) {
                        if (value.isEmpty) {
                          return 'title is empty';
                        } else {
                          return null;
                        }
                      },
                    ),
                    TextFormField(
                      controller: _descController,
                      decoration:
                          InputDecoration(labelText: widget.data['desc']), // Same goes here
                      validator: (String value) {
                        if (value.isEmpty) {
                          return 'description is empty';
                        } else {
                          return null;
                        }
                      },
                    ),
                  ],
                ),
              ),
            ),
          ),
        ),
        // The button associated with this form
        RaisedButton(
          shape:
              RoundedRectangleBorder(borderRadius: BorderRadius.circular(15.0)),
          child: Text('Update'),
          color: Colors.blue,
          onPressed: () async {
            // If validation is successful, then call the on pressed function we assigned to the widget. // Check the MyWidget class
            if (_formKey.currentState.validate()) {
              await widget.onPressed(_titleController.text, _descController.text); // Instead of putting firebase update code here, we are passing the title and description to our main widget from where we will post
            }
          },
        ),
      ],
    );
  }
}

// Our main widget
class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Demo'),
      ),
      // Wrap this up in your stream builder
      // I am using a listview with mock data for the sake of this example.
      body: ListView.builder(
      itemBuilder: (context, index) {
        // We create a new instance of our custom form and we don't need to manage any controllers or keys. We just need to pass the data and what happens when we press the update button in our custom form.
        // Here is why we defined a type named onFormData before.
        // You can simply post updates in your form widget directly if your logic is same for each form
        // We are getting the title and description info here through our custom defined Forms without managing any keys and controllers.
        // Also this method is async so you can post your firebase updates from here waiting for them to complete using await
        return MyForm(data: _mockData[index], onPressed: (String title, String description) async {
          // Put your firebase update code here
          _mockData[index]['title'] = title;
          _mockData[index]['desc'] = description;
          Navigator.of(context).pop(); // Go back after the updates are made as written in your example
        });
      },
      physics: BouncingScrollPhysics(),
      itemCount: _mockData.length, // Length of the data.
        ),
    );
  }
}

Before any updates:

After writing your title and description:

After pressing update, when you go back to the same screen:

Hope this helps!


来源: stackexchange

问:
Why does my PHP string comparison fail?
I have the following snippet of code

```<code>if ($summary == "CFD funding Interest Paid" ||
    $summary == "Commissions" ||
    $summary == "Closing trades") {
    print $summary.",".$date.",".$reference.",".$description.",".$amount."<br>";
}
else {
    print $summary."*<br>";
}
</code>```

It outputs the following

```
Commissions*
Commissions*
Closing trades*
Commissions*
Closing trades*
```

How come the strings do not appear to be matching?

答:
Perhaps you have leading whitespace?
You could trim() that away to see if it helps?</p>

ContentLicense: CC BY-SA 3.0

Title: Why does my PHP string comparison fail?

Body:
I have the following snippet of code

if ($summary == "CFD funding Interest Paid" ||
    $summary == "Commissions" ||
    $summary == "Closing trades") {
    print $summary.",".$date.",".$reference.",".$description.",".$amount."
";
}
else {
    print $summary."*
";
}

It outputs the following

Commissions*
Commissions*
Closing trades*
Commissions*
Closing trades*

How come the strings do not appear to be matching?


问:
Android - Store ArrayList persistent
My app is displaying a list of various categories (herbs, side dishes, ..) in a RecyclerView. Depending on the category you clicked on, a new Activity with a new RecylcerView opens containing all the ingredients.

Right now I have an ArrayList which gets filled with the ingredients via ".add" depending on the choosen category.

The problem im facing right now is, that I want to implement an option for the user to add own Ingredients. I tried storing the ArrayList containing the ingredients in SharedPreferences by using Gson, but I couldn't manage to add elements, since it always overwrote the current list.

What would be the best way to store the ingredients? A room, sqlite, ..?
Without further explanation, the ingredient list will only contain about 70 items max.

Thanks in advance.

Edit:

CatList.kt

class CatList : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_cat_list)

        //Create List for categories
        val cats = ArrayList<IngCat>()

        //Fill categories
        cats.add(IngCat(R.drawable.herbs, "Herbs"))
        cats.add(IngCat(R.drawable.fluessiges, "Liquids"))
        cats.add(IngCat(R.drawable.festes, "Solids"))
        cats.add(IngCat(R.drawable.beilagen, "Sides"))

        //Recyclerview
        id_rv_CatList.layoutManager = LinearLayoutManager(this)
        id_rv_CatList.adapter =
            CatListAdapter(cats) {listItem, position -> //go to Ingredient List Activity
                    goToIngList(position, listItem.name)
                }

        //id_rv_CatList.addItemDecoration(DividerItemDecoration(this,DividerItemDecoration.HORIZONTAL))

        //actionbar
        val actionbar = supportActionBar
        //set actionbar title
        actionbar!!.title = "Ingredient - Categories"

    }
    private fun goToIngList(cat: Int, name: String){
        val intent = Intent(this, IngList::class.java)
        intent.putExtra("Category", cat)
        intent.putExtra("Name", name)
        startActivity(intent)
    }
}

data class IngCat(var mImageResource:Int, var name:String)```
</div>
</div>
</p>

<p><strong>IngList.kt</strong></p>

<p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-js lang-js prettyprint-override"><code>class IngList : AppCompatActivity() {

    companion object {
        var categoryChoosen : Int = 0
        var catName : String = "Err"
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_ing_list)

        //Initilize Ingredient List
        val ings :ArrayList<IngIng> = ArrayList()

        //Get category and category name
        categoryChoosen = intent.getIntExtra("Kategorie",0)
        catName = intent.getStringExtra("Name")!!

       when (categoryChoosen) {
            0 -> {
                ings.add(IngIng("https://doeel.com/images/thumbnails/1100/900/detailed    /92/Turmeric_Powder___Holud_Gura__.png", "Turmeric Powder"))
            }
            1 -> ings.add(IngIng("https://www.miraherba.de/4923-large_default/bio-ghee-300-g.jpg", "Ghee"))
            2 -> ings.add(IngIng("https://www.organicfacts.net/wp-content/uploads/coriander-1.jpg", "Coriander leaves"))
            3 -> ings.add(IngIng("https://gbc-cdn-public-media.azureedge.net/img75602.1426x713.jpg", "Potatoes"))
        }

        //Actionbar Settings
        setSupportActionBar(toolbar)
        val actionbar = supportActionBar
        actionbar!!.title = "Ingredients- $catName"
        actionbar.setDisplayHomeAsUpEnabled(true)

        //Recyclerview
        id_rv_IngList.layoutManager = GridLayoutManager(this,2)
        id_rv_IngList.adapter =
            IngListAdapter(ings) {//ClickListener RecyclerView
                Toast.makeText(this, "Item clicked: ${it.name}", Toast.LENGTH_SHORT).show()
            }

//Actionbar
    }
    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        // Inflate the menu; this adds items to the action bar if it is present.
        menuInflater.inflate(R.menu.actionbar_ing_list, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return when (item.itemId) {
            R.id.id_menu_action_add -> {
                val intent = Intent(this, AddIngredient::class.java)
                startActivity(intent)
                true
            }
            else -> super.onOptionsItemSelected(item)

    }
}

override fun onSupportNavigateUp(): Boolean {
        onBackPressed()
        return true
    }

}</code>```

IngListAdapter.kt

class IngListAdapter (private val ings: ArrayList<IngIng>, val clickListener: (IngIng)->Unit): RecyclerView.Adapter<RecyclerView.ViewHolder>(){

    override fun getItemCount(): Int = ings.size

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val v: View = LayoutInflater.from(parent.context).inflate(R.layout.recyclerview_ing_list_item, parent, false)
        return IngViewHolder(v)
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        var currentItem = ings.get(position)
        when (holder) {
            is IngViewHolder -> {
                holder.tvIngList.text = currentItem.name
               // holder.ivIngImage.setImageResource(currentItem.mImageResource)
                Picasso.get().load(currentItem.mImageResource).placeholder(R.drawable.ic_broken_image_black_200dp).error(R.drawable.ic_broken_image_red_24dp).into(holder.ivIngImage)

                holder.cvIngCard.setOnClickListener{
                        clickListener(currentItem)
                    }
                }
            }

        }
    }

    class IngViewHolder (view: View) : RecyclerView.ViewHolder(view) {

        val tvIngList: TextView = view.id_text_ing
        val ivIngImage: ImageView = view.id_img_ing
        val cvIngCard: MaterialCardView = view.id_cv_ing_list
    }```

答:
I personally think Json/Gson in a SharedPreference is the easiest way to go if there are so few items. The way I would handle it is to store the list in memory at application startup, and persist the list back to the SharedPreference when the app is shut down. Also when the app gets stopped for good measure because you can't 100% be sure onDestroy will be called.

So first I'd make a class to store the data. If you were using Fragments that all are in the same Activity, you'd put this in a ViewModel. But since they are separate Activities, you need a singleton for them. (Google doesn't recommend using multiple Activities because it's hard to share data between them. But it's not impossible. It's what we did before Fragments.)

To do it as a singleton, you could have a class like this:

```<code>class IngredientsRepo private constructor (application: Application) {

    companion object {
        private val INSTANCE: IngredientsRepo? = null
        fun getInstance(application: Application) =
            INSTANCE ?: IngredientsRepo(application).also { INSTANCE = it }

        private const KEY_JSON_PREF = "ingredientsJson"
    }

    private val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(application)

    val herbsList: MutableList<IngCat>
    val liquidsList: MutableList<IngCat>
    val solidsList: MutableList<IngCat>
    val sidesList: MutableList<IngCat>

    init {
        val json = sharedPreferences.getString(KEY_JSON_PREF, null)
        if (json == null) {
            // initialize your list contents for the first time
        } else {
            // convert your json and fill the data into your lists
        }
    }

    fun save {
        val jsonString = // Convert your lists to Json
        sharedPreferences.edit().putString(KEY_JSON_PREF, jsonString).apply()
    }
}

</code>```

This class becomes responsible for setting up your lists. You can retrieve it from any Activity with IngredientsRepo.getInstance(this) and you can add and remove items from the lists whenever you like. You can also call save on it whenever you like to persist the latest data. It's probably sufficient to do this in onStop() of any Activity that modifies the list.

More properly, the data in this class would only be exposed with immutable lists, and you'd add functions for adding and removing items, so only this class directly modifies the lists. I didn't want to overcomplicate the example, but it would be better for encapsulation to not have Activities (which are supposed to be pure UI components) directly modifying data structures.

ContentLicense: CC BY-SA 4.0

Title: Android - Store ArrayList persistent

Body:
My app is displaying a list of various categories (herbs, side dishes, ..) in a RecyclerView. Depending on the category you clicked on, a new Activity with a new RecylcerView opens containing all the ingredients.

Right now I have an ArrayList which gets filled with the ingredients via ".add" depending on the choosen category.

The problem im facing right now is, that I want to implement an option for the user to add own Ingredients. I tried storing the ArrayList containing the ingredients in SharedPreferences by using Gson, but I couldn't manage to add elements, since it always overwrote the current list.

What would be the best way to store the ingredients? A room, sqlite, ..?
Without further explanation, the ingredient list will only contain about 70 items max.

Thanks in advance.

Edit:

CatList.kt

class CatList : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_cat_list)

        //Create List for categories
        val cats = ArrayList<IngCat>()

        //Fill categories
        cats.add(IngCat(R.drawable.herbs, "Herbs"))
        cats.add(IngCat(R.drawable.fluessiges, "Liquids"))
        cats.add(IngCat(R.drawable.festes, "Solids"))
        cats.add(IngCat(R.drawable.beilagen, "Sides"))

        //Recyclerview
        id_rv_CatList.layoutManager = LinearLayoutManager(this)
        id_rv_CatList.adapter =
            CatListAdapter(cats) {listItem, position -> //go to Ingredient List Activity
                    goToIngList(position, listItem.name)
                }

        //id_rv_CatList.addItemDecoration(DividerItemDecoration(this,DividerItemDecoration.HORIZONTAL))

        //actionbar
        val actionbar = supportActionBar
        //set actionbar title
        actionbar!!.title = "Ingredient - Categories"

    }
    private fun goToIngList(cat: Int, name: String){
        val intent = Intent(this, IngList::class.java)
        intent.putExtra("Category", cat)
        intent.putExtra("Name", name)
        startActivity(intent)
    }
}

data class IngCat(var mImageResource:Int, var name:String)

IngList.kt

class IngList : AppCompatActivity() {

    companion object {
        var categoryChoosen : Int = 0
        var catName : String = "Err"
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_ing_list)

        //Initilize Ingredient List
        val ings :ArrayList<IngIng> = ArrayList()

        //Get category and category name
        categoryChoosen = intent.getIntExtra("Kategorie",0)
        catName = intent.getStringExtra("Name")!!

       when (categoryChoosen) {
            0 -> {
                ings.add(IngIng("https://doeel.com/images/thumbnails/1100/900/detailed    /92/Turmeric_Powder___Holud_Gura__.png", "Turmeric Powder"))
            }
            1 -> ings.add(IngIng("https://www.miraherba.de/4923-large_default/bio-ghee-300-g.jpg", "Ghee"))
            2 -> ings.add(IngIng("https://www.organicfacts.net/wp-content/uploads/coriander-1.jpg", "Coriander leaves"))
            3 -> ings.add(IngIng("https://gbc-cdn-public-media.azureedge.net/img75602.1426x713.jpg", "Potatoes"))
        }

        //Actionbar Settings
        setSupportActionBar(toolbar)
        val actionbar = supportActionBar
        actionbar!!.title = "Ingredients- $catName"
        actionbar.setDisplayHomeAsUpEnabled(true)

        //Recyclerview
        id_rv_IngList.layoutManager = GridLayoutManager(this,2)
        id_rv_IngList.adapter =
            IngListAdapter(ings) {//ClickListener RecyclerView
                Toast.makeText(this, "Item clicked: ${it.name}", Toast.LENGTH_SHORT).show()
            }

//Actionbar
    }
    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        // Inflate the menu; this adds items to the action bar if it is present.
        menuInflater.inflate(R.menu.actionbar_ing_list, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return when (item.itemId) {
            R.id.id_menu_action_add -> {
                val intent = Intent(this, AddIngredient::class.java)
                startActivity(intent)
                true
            }
            else -> super.onOptionsItemSelected(item)

    }
}

override fun onSupportNavigateUp(): Boolean {
        onBackPressed()
        return true
    }

}

IngListAdapter.kt

class IngListAdapter (private val ings: ArrayList<IngIng>, val clickListener: (IngIng)->Unit): RecyclerView.Adapter<RecyclerView.ViewHolder>(){

    override fun getItemCount(): Int = ings.size

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val v: View = LayoutInflater.from(parent.context).inflate(R.layout.recyclerview_ing_list_item, parent, false)
        return IngViewHolder(v)
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        var currentItem = ings.get(position)
        when (holder) {
            is IngViewHolder -> {
                holder.tvIngList.text = currentItem.name
               // holder.ivIngImage.setImageResource(currentItem.mImageResource)
                Picasso.get().load(currentItem.mImageResource).placeholder(R.drawable.ic_broken_image_black_200dp).error(R.drawable.ic_broken_image_red_24dp).into(holder.ivIngImage)

                holder.cvIngCard.setOnClickListener{
                        clickListener(currentItem)
                    }
                }
            }

        }
    }

    class IngViewHolder (view: View) : RecyclerView.ViewHolder(view) {

        val tvIngList: TextView = view.id_text_ing
        val ivIngImage: ImageView = view.id_img_ing
        val cvIngCard: MaterialCardView = view.id_cv_ing_list
    }

Body:
I personally think Json/Gson in a SharedPreference is the easiest way to go if there are so few items. The way I would handle it is to store the list in memory at application startup, and persist the list back to the SharedPreference when the app is shut down. Also when the app gets stopped for good measure because you can't 100% be sure onDestroy will be called.

So first I'd make a class to store the data. If you were using Fragments that all are in the same Activity, you'd put this in a ViewModel. But since they are separate Activities, you need a singleton for them. (Google doesn't recommend using multiple Activities because it's hard to share data between them. But it's not impossible. It's what we did before Fragments.)

To do it as a singleton, you could have a class like this:

class IngredientsRepo private constructor (application: Application) {

    companion object {
        private val INSTANCE: IngredientsRepo? = null
        fun getInstance(application: Application) =
            INSTANCE ?: IngredientsRepo(application).also { INSTANCE = it }

        private const KEY_JSON_PREF = "ingredientsJson"
    }

    private val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(application)

    val herbsList: MutableList<IngCat>
    val liquidsList: MutableList<IngCat>
    val solidsList: MutableList<IngCat>
    val sidesList: MutableList<IngCat>

    init {
        val json = sharedPreferences.getString(KEY_JSON_PREF, null)
        if (json == null) {
            // initialize your list contents for the first time
        } else {
            // convert your json and fill the data into your lists
        }
    }

    fun save {
        val jsonString = // Convert your lists to Json
        sharedPreferences.edit().putString(KEY_JSON_PREF, jsonString).apply()
    }
}

This class becomes responsible for setting up your lists. You can retrieve it from any Activity with IngredientsRepo.getInstance(this) and you can add and remove items from the lists whenever you like. You can also call save on it whenever you like to persist the latest data. It's probably sufficient to do this in onStop() of any Activity that modifies the list.

More properly, the data in this class would only be exposed with immutable lists, and you'd add functions for adding and removing items, so only this class directly modifies the lists. I didn't want to overcomplicate the example, but it would be better for encapsulation to not have Activities (which are supposed to be pure UI components) directly modifying data structures.


问:
Single form multiple submit into same array
I was trying to push with a single form using the $_POST method multiple times the same form (with different values) until the array index is 4 (or a number I decide).

So with this html form i want to press submit, push the values into array, then refresh page, reinsert different values and so on until the condition is true.

```<code><?php
if (!isset($count)) {
    $person = array(
        array(
            'name' => '',
            'surname' => '',
            'phoneNumber' => ''
        )
    );
}
var_dump($person);
if (!isset($_POST['submit'])) {

    echo "<form action=\"index.php\" method=\"post\">
        <label for=\"name\">Name</label>
        <input type=\"text\" name=\"name\" required>
        <br>
        <label for=\"surname\">Surname</label>
        <input type=\"text\" name=\"surname\" required>
        <br>
        <label for=\"phoneNumber\">Phone Number</label>
        <input type=\"text\" name=\"phoneNumber\" required>
        <br>
        <input type=\"submit\" value=\"Submit\" name=\"submit\">
    </form>";
    $count = 0;
} else {
    $name = $_POST['name'];
    $surname = $_POST['surname'];
    $phoneNumber = $_POST['phoneNumber'];

    if (count($person) <= 2) {
        array_push($person, $name, $surname, $phoneNumber);
        //echo "<meta http-equiv=\"refresh\" content=\"0\">";
        //echo "Sto inserendo persone";
        //echo count($persone);
        echo count($person);
        //var_dump($persone);
        //print_r($persone);
    } else {
        var_dump($person);
    };
}

?>
</code>```

I was thinking about using $_SESSION but I don't have an idea about how to use it.

I don't want to use AJAX or jQuery or Javascript only pure PHP.

答:
The example below shows always the form and your actual persons array. If you submit the form, your data will add to the array until it counts more than three entries. I think that is what you are looking for:

```<code><?php
session_start();

if (!isset($_SESSION['persons'])) {
    $_SESSION['persons'] = [];
}

if(isset($_POST['submit'])) {
  if (count($_SESSION['persons']) <= 2) {
    $_SESSION['persons'][] = array(
      'name' => $_POST['name'],
      'surname' => $_POST['surname'],
      'phoneNumber' => $_POST['phoneNumber']
    );
  }
}
?>

```<?php var_dump($_SESSION['persons']); ?>```

<form action="index.php" method="post">
  <label for="name">Name</label>
  <input type="text" name="name" required><br>
  <label for="surname">Surname</label>
  <input type="text" name="surname" required><br>
  <label for="phoneNumber">Phone Number</label>
  <input type="text" name="phoneNumber" required><br>
  <input type="submit" value="Submit" name="submit">
</form>
</code>```

With the following line of code you can clear you array if you need to:

```<code>$_SESSION['persons'] = [];
</code>```

Body:
I was trying to push with a single form using the $_POST method multiple times the same form (with different values) until the array index is 4 (or a number I decide).

So with this html form i want to press submit, push the values into array, then refresh page, reinsert different values and so on until the condition is true.

<?php
if (!isset($count)) {
    $person = array(
        array(
            'name' => '',
            'surname' => '',
            'phoneNumber' => ''
        )
    );
}
var_dump($person);
if (!isset($_POST['submit'])) {

    echo "<form action=\"index.php\" method=\"post\">
        Name
        <input type=\"text\" name=\"name\" required>

        Surname
        <input type=\"text\" name=\"surname\" required>

        Phone Number
        <input type=\"text\" name=\"phoneNumber\" required>

        <input type=\"submit\" value=\"Submit\" name=\"submit\">
    </form>";
    $count = 0;
} else {
    $name = $_POST['name'];
    $surname = $_POST['surname'];
    $phoneNumber = $_POST['phoneNumber'];

    if (count($person) <= 2) {
        array_push($person, $name, $surname, $phoneNumber);
        //echo "<meta http-equiv=\"refresh\" content=\"0\">";
        //echo "Sto inserendo persone";
        //echo count($persone);
        echo count($person);
        //var_dump($persone);
        //print_r($persone);
    } else {
        var_dump($person);
    };
}

?>

I was thinking about using $_SESSION but I don't have an idea about how to use it.

I don't want to use AJAX or jQuery or Javascript only pure PHP.

Body:
The example below shows always the form and your actual persons array. If you submit the form, your data will add to the array until it counts more than three entries. I think that is what you are looking for:

<?php
session_start();

if (!isset($_SESSION['persons'])) {
    $_SESSION['persons'] = [];
}

if(isset($_POST['submit'])) {
  if (count($_SESSION['persons']) <= 2) {
    $_SESSION['persons'][] = array(
      'name' => $_POST['name'],
      'surname' => $_POST['surname'],
      'phoneNumber' => $_POST['phoneNumber']
    );
  }
}
?>

<pre><?php var_dump($_SESSION['persons']); ?></pre>

<form action="index.php" method="post">
  <label for="name">Name</label>
  <input type="text" name="name" required><br>
  <label for="surname">Surname</label>
  <input type="text" name="surname" required><br>
  <label for="phoneNumber">Phone Number</label>
  <input type="text" name="phoneNumber" required><br>
  <input type="submit" value="Submit" name="submit">
</form>

With the following line of code you can clear you array if you need to:

$_SESSION['persons'] = [];


问:
Cosmos DB - Slow COUNT
I am working on an existing Cosmos DB where the number of physical partitions is less than 100. Each contains around 30,000,000 documents. There is an indexing policy in place on "/*".

I'm just trying to get a total count from SQL API like so:

```<code>SELECT VALUE COUNT(1) FROM mycollection c
</code>```

I have set EnableCrossPartitionQuery to true, and MaxDegreeOfParallelism to 100 (so as to at least cover the number of physical partitions AKA key ranges). The database is scaled to 50,000 RU. The query is running for HOURS. This does not make sense to me. An equivalent relational database would answer this question almost immediately. This is ridiculous.

What, if anything, can I change here? Am I doing something wrong?

答: Microsoft support ended up applying an update to the underlying instance. In this case, the update was in the development pipeline to be rolled out gradually. This instance got it earlier as a result of the support case. The update related to using indexes to service this type of query.</p>

Title: Cosmos DB - Slow COUNT

Body:
I am working on an existing Cosmos DB where the number of physical partitions is less than 100. Each contains around 30,000,000 documents. There is an indexing policy in place on "/*".

I'm just trying to get a total count from SQL API like so:

SELECT VALUE COUNT(1) FROM mycollection c

I have set EnableCrossPartitionQuery to true, and MaxDegreeOfParallelism to 100 (so as to at least cover the number of physical partitions AKA key ranges). The database is scaled to 50,000 RU. The query is running for HOURS. This does not make sense to me. An equivalent relational database would answer this question almost immediately. This is ridiculous.

What, if anything, can I change here? Am I doing something wrong?


问:
Bash regex that returns short alphanumeric operator name from AT command AT+COPS
I'm using a bash script with the AT command AT+COPS=? which returns the following string :

```<code>+COPS: (1,"Orange F","Orange","20801",2),(1,"Swisscom","Swisscom","22801",7),(1,"Swisscom","Swisscom","22801",2),(1,"Salt","Salt","22803",2),(1,"Sunrise","Sunrise","22802",2),(1,"Sunrise","Sunrise","22802",7),(1,"Sunrise","Sunrise","22802",0),(2,"Salt","Salt","22803",7),(1,"Free","Free","20815",2),(1,"F SFR","SFR","20810",7),(1,"F-Bouygues Telecom","BYTEL","20820",7),,(0-4),(0-2)
</code>```

And I'm trying to find a regular expression to match every short alphanumeric operator names. So here, it's :

```<code>Orange Swisscom Swisscom Salt Sunrise Sunrise Sunrise Salt Free SFR BYTEL
</code>```

For example, in the group

```<code>(1,"F-Bouygues Telecom","BYTEL","20820",7)
</code>```

It's the 'BYTEL' part that is interesting. 'BYTEL' could be also lower-case chars and numbers.

I tried multiple solution but they are all not 100% matching. For the moment, I'm using :

```<code> grep -oP '"([a-zA-z])\w+"'
</code>```

but it would not work in some special cases and is matching also the long alphanumeric operator names (first name between quotes).

答:
Try this sed variant

```<code>sed 's/(/\n/g' file | sed -n 's/.,".*","\(.*\)",".*".*/\1/p'
</code>```

Your test string is in file, the output

```<code>Orange
Swisscom
Swisscom
Salt
Sunrise
Sunrise
Sunrise
Salt
Free
SFR
BYTEL
</code>```

Body:
I'm using a bash script with the AT command AT+COPS=? which returns the following string :

+COPS: (1,"Orange F","Orange","20801",2),(1,"Swisscom","Swisscom","22801",7),(1,"Swisscom","Swisscom","22801",2),(1,"Salt","Salt","22803",2),(1,"Sunrise","Sunrise","22802",2),(1,"Sunrise","Sunrise","22802",7),(1,"Sunrise","Sunrise","22802",0),(2,"Salt","Salt","22803",7),(1,"Free","Free","20815",2),(1,"F SFR","SFR","20810",7),(1,"F-Bouygues Telecom","BYTEL","20820",7),,(0-4),(0-2)

And I'm trying to find a regular expression to match every short alphanumeric operator names. So here, it's :

Orange Swisscom Swisscom Salt Sunrise Sunrise Sunrise Salt Free SFR BYTEL

For example, in the group

(1,"F-Bouygues Telecom","BYTEL","20820",7)

It's the 'BYTEL' part that is interesting. 'BYTEL' could be also lower-case chars and numbers.

I tried multiple solution but they are all not 100% matching. For the moment, I'm using :

 grep -oP '"([a-zA-z])\w+"'

but it would not work in some special cases and is matching also the long alphanumeric operator names (first name between quotes).

Body:
Try this sed variant

sed 's/(/\n/g' file | sed -n 's/.,".*","\(.*\)",".*".*/\1/p'

Your test string is in file, the output

Orange
Swisscom
Swisscom
Salt
Sunrise
Sunrise
Sunrise
Salt
Free
SFR
BYTEL


问:
dictSession.getSchema is not a function (Node.js/MySQL/xdevapi)
I have started using xdevapi for Node.js as mysql connector. By following this guide (https://dev.mysql.com/doc/x-devapi-userguide/en/connecting-to-a-single-mysqld-node-setup.html):

```<code>var mysqlx = require('@mysql/xdevapi');

var dictSession = mysqlx.getSession( {
        host: 'localhost', 'port': 33060,
        user: 'root', password: '' } )

var db1 = dictSession.getSchema('test')
</code>```

I got an error:

dictSession.getSchema is not a function

答:
You are using synchronous JavaScript syntax that only works in the MySQL Shell (as depicted in the link you point to). Unfortunately, that guide does not seem to include a proper snippet for the Connector/Node.js version where the getSession() method is asynchronous and returns a Promise, which means you need to attach a proper then() handler, in which dictSession will eventually be resolved.

```<code>mysqlx.getSession({ host: 'localhost', 'port': 33060, user: 'root', password: '' })
  .then(function (dictSession) {
    var db1 = dictSession.getSchema('test')
  });
</code>```

or you can use the async/await flavour:

```<code>var dictSession = await mysqlx.getSession({ host: 'localhost', 'port': 33060, user: 'root', password: '' })
var db1 = dictSession.getSchema('test')
</code>```

I'll make sure the guide will include a proper example.

Disclaimer: I'm the X DevAPI Node.js connector lead dev.

Body:
I have started using xdevapi for Node.js as mysql connector. By following this guide (https://dev.mysql.com/doc/x-devapi-userguide/en/connecting-to-a-single-mysqld-node-setup.html):

var mysqlx = require('@mysql/xdevapi');

var dictSession = mysqlx.getSession( {
        host: 'localhost', 'port': 33060,
        user: 'root', password: '' } )

var db1 = dictSession.getSchema('test')

I got an error:

dictSession.getSchema is not a function

Body:
You are using synchronous JavaScript syntax that only works in the MySQL Shell (as depicted in the link you point to). Unfortunately, that guide does not seem to include a proper snippet for the Connector/Node.js version where the getSession() method is asynchronous and returns a Promise, which means you need to attach a proper then() handler, in which dictSession will eventually be resolved.

mysqlx.getSession({ host: 'localhost', 'port': 33060, user: 'root', password: '' })
  .then(function (dictSession) {
    var db1 = dictSession.getSchema('test')
  });

or you can use the async/await flavour:

var dictSession = await mysqlx.getSession({ host: 'localhost', 'port': 33060, user: 'root', password: '' })
var db1 = dictSession.getSchema('test')

I'll make sure the guide will include a proper example.

Disclaimer: I'm the X DevAPI Node.js connector lead dev.


问:
Looping within a coroutine
I have written the following snippet in order to play five clicking sounds resembling a rotating wheel.

How can I make a loop out of it, so that the clicks keep on playing until I call the stop function at the bottom?

I toggled on the loop feature on each sound file, but they still each play only once...

public void PlayClickSounds()
{
    StartCoroutine( ClickSounds(0.5f) );
}

private IEnumerator ClickSounds(float clipsGapDuration)
{
    Play(SpinningSoundClick1);
    yield return new WaitForSeconds(clipsGapDuration);
    Play(SpinningSoundClick2);
    yield return new WaitForSeconds(clipsGapDuration);
    Play(SpinningSoundClick3);
    yield return new WaitForSeconds(clipsGapDuration);
    Play(SpinningSoundClick4);
    yield return new WaitForSeconds(clipsGapDuration);
    Play(SpinningSoundClick5);
    yield return new WaitForSeconds(clipsGapDuration);
}

public void StopClickSounds()
{
    StopCoroutine( SpinningClickSounds(0.5f) );
}
```

答:
You should use a while loop. I don't see your setup but you should also rather use a list like e.g.

[SerializeField] private List<AudioClip> _boostWheelSpinningSoundClicks = new List<AudioClip>();

private int _currentIndex;
private Coroutine _currentRoutine;

public void PlayClickSounds()
{
    if(_currentRoutine != null)
    {
        Debug.LogWarning("Already playing");
        return;
    }

    _currentRoutine = StartCoroutine(ClickSounds(0.5f));
}

private IEnumerator ClickSounds(float clipsGapDuration)
{
    // This looks dangerous but is allowed in
    // Coroutines as long as you yield somewhere inside
    while(true)
    {
        _currentIndex = (_currentIndex + 1) % _boostWheelSpinningSoundClicks.Count;

        var currentClip = _boostWheelSpinningSoundClicks[_currentIndex];
        Play(currentClip);
        yield return new WaitForSeconds(clipsGapDuration);
    }
}

public void StopClickSounds()
{
    if(_currentRoutine == null)
    {
        Debug.LogWarning("Not playing");
        return;
    }

    StopCoroutine(_currentRoutine);
}
```

Title: Looping within a coroutine


问:
how to fix the error "error creating bean with name...."
when I run my application there is the following error displayed:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'pamdaBatchConfigurer': Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'getJobRepository' defined in com.orange.pamda.config.PamdaBatchConfigurer: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.core.repository.JobRepository]: Circular reference involving containing bean 'pamdaBatchConfigurer' - consider declaring the factory method as static for independence from its containing instance. Factory method 'getJobRepository' threw exception; nested exception is java.lang.IllegalArgumentException: DatabaseType not found for product name: [MariaDB]
      at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:137)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:409)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1620)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
      at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
      at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
      at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
      at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
      at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
      at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
      at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
      at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:443)
      at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:325)
      at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)
      at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4685)
      at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5146)
      at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
      at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1384)
      at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1374)
      at java.util.concurrent.FutureTask.run(FutureTask.java:266)
      at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
      at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
      at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909)
      at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:841)
      at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
      at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1384)
      at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1374)
      at java.util.concurrent.FutureTask.run(FutureTask.java:266)
      at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
      at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
      at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909)
      at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262)
      at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
      at org.apache.catalina.core.StandardService.startInternal(StandardService.java:421)
      at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
      at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:930)
      at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
      at org.apache.catalina.startup.Catalina.start(Catalina.java:633)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:498)
      at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:343)
      at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:474)

here is my file "pamdabatchconfigurer.java":

```<code>    package com.orange.pamda.config;

import java.util.Date;
import java.util.Set;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;

import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.configuration.annotation.BatchConfigurer;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.explore.JobExplorer;
import org.springframework.batch.core.explore.support.JobExplorerFactoryBean;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.Transactional;

import com.orange.pamda.config.batch.listener.SendFileAfterExportListener;
import com.orange.pamda.worker.config.CatalogueExporterJobConfiguration;
import com.orange.pamda.worker.config.CatalogueImporterJobConfiguration;
import com.orange.pamda.worker.config.CommonJobConfiguration;
import com.orange.pamda.worker.config.DataExporterJobConfiguration;
import com.orange.pamda.worker.config.HierarchyValidatorJobConfiguration;
import com.orange.pamda.worker.config.JobBuilderFactory;
import com.orange.pamda.worker.config.KoalaExporterJobConfiguration;
import com.orange.pamda.worker.config.MappingExporterJobConfiguration;
import com.orange.pamda.worker.config.MappingImporterJobConfiguration;
import com.orange.pamda.worker.config.OrphanExporterJobConfiguration;
import com.orange.pamda.worker.config.ReleaseJobConfiguration;
import com.orange.pamda.worker.config.SummaryExporterJobConfiguration;

@Configuration
@EnableBatchProcessing(modular = true)
@Import({ CommonJobConfiguration.class, CatalogueExporterJobConfiguration.class,
        CatalogueImporterJobConfiguration.class, DataExporterJobConfiguration.class,
        HierarchyValidatorJobConfiguration.class, KoalaExporterJobConfiguration.class,
        MappingExporterJobConfiguration.class, MappingImporterJobConfiguration.class,
        OrphanExporterJobConfiguration.class, ReleaseJobConfiguration.class, SummaryExporterJobConfiguration.class })
public class PamdaBatchConfigurer implements BatchConfigurer {

    @Autowired
    private PlatformTransactionManager transactionManager;

    @Autowired
    private DataSource dataSource;

    @Override
    @Bean
    public JobRepository getJobRepository() throws Exception {
        JobRepositoryFactoryBean jobRepositoryFactoryBean = new JobRepositoryFactoryBean();
        jobRepositoryFactoryBean.setDataSource(dataSource);
        jobRepositoryFactoryBean.setTransactionManager(transactionManager);
        jobRepositoryFactoryBean.setIsolationLevelForCreate("ISOLATION_DEFAULT");
        jobRepositoryFactoryBean.afterPropertiesSet();
        return jobRepositoryFactoryBean.getObject();
    }

    @Override
    public PlatformTransactionManager getTransactionManager() throws Exception {
        return transactionManager;
    }

    @Override
    @Bean
    public JobLauncher getJobLauncher() throws Exception {
        SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
        jobLauncher.setJobRepository(getJobRepository());
        // jobLauncher.setTaskExecutor(getTaskExecutor());
        jobLauncher.afterPropertiesSet();
        return jobLauncher;
    }

    @Override
    @Bean
    public JobExplorer getJobExplorer() throws Exception {
        JobExplorerFactoryBean jobExplorerFactoryBean = new JobExplorerFactoryBean();
        jobExplorerFactoryBean.setDataSource(dataSource);
        jobExplorerFactoryBean.afterPropertiesSet();
        return jobExplorerFactoryBean.getObject();
    }

    // @Bean
    // public TaskExecutor getTaskExecutor() {
    // SimpleAsyncTaskExecutor simpleAsyncTaskExecutor = new
    // SimpleAsyncTaskExecutor();
    // simpleAsyncTaskExecutor.setConcurrencyLimit(1000); // no throttle
    // return simpleAsyncTaskExecutor;
    // }

    @Bean
    public JobBuilderFactory getJobBuilderFactory() throws Exception {
        return new JobBuilderFactory(getJobRepository(), sendFileAfterExportListener());
    }

    @Bean
    public StepBuilderFactory getStepBuilderFactory() throws Exception {
        return new StepBuilderFactory(getJobRepository(), transactionManager);
    }

    @Bean
    public SendFileAfterExportListener sendFileAfterExportListener() {
        return new SendFileAfterExportListener();
    }

    @PostConstruct
    @Transactional
    public void init() throws Exception {
        JobExplorer jobExplorer = getJobExplorer();
        JobRepository jobRepository = getJobRepository();
        for (String jobName : jobExplorer.getJobNames()) {
            Set<JobExecution> runningJobExecutions = jobExplorer.findRunningJobExecutions(jobName);
            for (JobExecution runningJobExecution : runningJobExecutions) {
                runningJobExecution.setExitStatus(ExitStatus.UNKNOWN);
                runningJobExecution.setEndTime(new Date());
                jobRepository.update(runningJobExecution);
            }
        }
    }

}
</code>```

I really do not know where this error comes from can someone help me please?

答:
Could you please check this part of the exception, that you have added. It might be the reason : "Circular reference involving".

Circular reference involving containing bean 'pamdaBatchConfigurer' -
  consider declaring the factory method as static for independence from
  its containing instance.

Body:
when I run my application there is the following error displayed:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'pamdaBatchConfigurer': Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'getJobRepository' defined in com.orange.pamda.config.PamdaBatchConfigurer: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.core.repository.JobRepository]: Circular reference involving containing bean 'pamdaBatchConfigurer' - consider declaring the factory method as static for independence from its containing instance. Factory method 'getJobRepository' threw exception; nested exception is java.lang.IllegalArgumentException: DatabaseType not found for product name: [MariaDB]
      at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:137)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:409)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1620)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
      at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
      at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
      at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
      at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
      at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
      at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
      at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
      at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:443)
      at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:325)
      at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)
      at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4685)
      at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5146)
      at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
      at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1384)
      at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1374)
      at java.util.concurrent.FutureTask.run(FutureTask.java:266)
      at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
      at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
      at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909)
      at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:841)
      at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
      at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1384)
      at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1374)
      at java.util.concurrent.FutureTask.run(FutureTask.java:266)
      at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
      at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
      at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909)
      at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262)
      at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
      at org.apache.catalina.core.StandardService.startInternal(StandardService.java:421)
      at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
      at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:930)
      at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
      at org.apache.catalina.startup.Catalina.start(Catalina.java:633)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:498)
      at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:343)
      at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:474)

here is my file "pamdabatchconfigurer.java":

    package com.orange.pamda.config;

import java.util.Date;
import java.util.Set;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;

import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.configuration.annotation.BatchConfigurer;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.explore.JobExplorer;
import org.springframework.batch.core.explore.support.JobExplorerFactoryBean;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.Transactional;

import com.orange.pamda.config.batch.listener.SendFileAfterExportListener;
import com.orange.pamda.worker.config.CatalogueExporterJobConfiguration;
import com.orange.pamda.worker.config.CatalogueImporterJobConfiguration;
import com.orange.pamda.worker.config.CommonJobConfiguration;
import com.orange.pamda.worker.config.DataExporterJobConfiguration;
import com.orange.pamda.worker.config.HierarchyValidatorJobConfiguration;
import com.orange.pamda.worker.config.JobBuilderFactory;
import com.orange.pamda.worker.config.KoalaExporterJobConfiguration;
import com.orange.pamda.worker.config.MappingExporterJobConfiguration;
import com.orange.pamda.worker.config.MappingImporterJobConfiguration;
import com.orange.pamda.worker.config.OrphanExporterJobConfiguration;
import com.orange.pamda.worker.config.ReleaseJobConfiguration;
import com.orange.pamda.worker.config.SummaryExporterJobConfiguration;

@Configuration
@EnableBatchProcessing(modular = true)
@Import({ CommonJobConfiguration.class, CatalogueExporterJobConfiguration.class,
        CatalogueImporterJobConfiguration.class, DataExporterJobConfiguration.class,
        HierarchyValidatorJobConfiguration.class, KoalaExporterJobConfiguration.class,
        MappingExporterJobConfiguration.class, MappingImporterJobConfiguration.class,
        OrphanExporterJobConfiguration.class, ReleaseJobConfiguration.class, SummaryExporterJobConfiguration.class })
public class PamdaBatchConfigurer implements BatchConfigurer {

    @Autowired
    private PlatformTransactionManager transactionManager;

    @Autowired
    private DataSource dataSource;

    @Override
    @Bean
    public JobRepository getJobRepository() throws Exception {
        JobRepositoryFactoryBean jobRepositoryFactoryBean = new JobRepositoryFactoryBean();
        jobRepositoryFactoryBean.setDataSource(dataSource);
        jobRepositoryFactoryBean.setTransactionManager(transactionManager);
        jobRepositoryFactoryBean.setIsolationLevelForCreate("ISOLATION_DEFAULT");
        jobRepositoryFactoryBean.afterPropertiesSet();
        return jobRepositoryFactoryBean.getObject();
    }

    @Override
    public PlatformTransactionManager getTransactionManager() throws Exception {
        return transactionManager;
    }

    @Override
    @Bean
    public JobLauncher getJobLauncher() throws Exception {
        SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
        jobLauncher.setJobRepository(getJobRepository());
        // jobLauncher.setTaskExecutor(getTaskExecutor());
        jobLauncher.afterPropertiesSet();
        return jobLauncher;
    }

    @Override
    @Bean
    public JobExplorer getJobExplorer() throws Exception {
        JobExplorerFactoryBean jobExplorerFactoryBean = new JobExplorerFactoryBean();
        jobExplorerFactoryBean.setDataSource(dataSource);
        jobExplorerFactoryBean.afterPropertiesSet();
        return jobExplorerFactoryBean.getObject();
    }

    // @Bean
    // public TaskExecutor getTaskExecutor() {
    // SimpleAsyncTaskExecutor simpleAsyncTaskExecutor = new
    // SimpleAsyncTaskExecutor();
    // simpleAsyncTaskExecutor.setConcurrencyLimit(1000); // no throttle
    // return simpleAsyncTaskExecutor;
    // }

    @Bean
    public JobBuilderFactory getJobBuilderFactory() throws Exception {
        return new JobBuilderFactory(getJobRepository(), sendFileAfterExportListener());
    }

    @Bean
    public StepBuilderFactory getStepBuilderFactory() throws Exception {
        return new StepBuilderFactory(getJobRepository(), transactionManager);
    }

    @Bean
    public SendFileAfterExportListener sendFileAfterExportListener() {
        return new SendFileAfterExportListener();
    }

    @PostConstruct
    @Transactional
    public void init() throws Exception {
        JobExplorer jobExplorer = getJobExplorer();
        JobRepository jobRepository = getJobRepository();
        for (String jobName : jobExplorer.getJobNames()) {
            Set<JobExecution> runningJobExecutions = jobExplorer.findRunningJobExecutions(jobName);
            for (JobExecution runningJobExecution : runningJobExecutions) {
                runningJobExecution.setExitStatus(ExitStatus.UNKNOWN);
                runningJobExecution.setEndTime(new Date());
                jobRepository.update(runningJobExecution);
            }
        }
    }

}

I really do not know where this error comes from can someone help me please?


问:
How to prevent bottom views pushing up when keyboard opens
There are two edittext on a screen and a button on bottom of the screen, the problem is when I click on edittext and keyboard open ups the button at the bottom appears above the keyboard, I want bottom buton to be at its original place rather than moving up with keyboard. the button is bottom aligned

Thanks

P.S:
I have tried adjust pan, resize etc nothing working

```<code><activity
        android:screenOrientation="portrait"
        android:name=".activities.MainActivity"
        android:windowSoftInputMode="stateUnchanged|adjustResize"
        android:theme="@style/AppTheme"
     />
</code>```

XML:

```<code><androidx.constraintlayout.widget.ConstraintLayout
    android:id="@+id/linearLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/text_white"
    android:orientation="vertical"
    android:paddingTop="@dimen/_20sdp"
    android:elevation="5dp"
    tools:context=".fragments.login.LoginFragment">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/tv_welcome"
        android:layout_marginRight="@dimen/_40sdp"
        android:layout_marginStart="@dimen/_20sdp"
        app:layout_constraintLeft_toLeftOf="parent"
        android:maxLines="2"
        style="@style/headingText"
        android:text="Welcome to the World \nof PACKR" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAllCaps="false"
        android:id="@+id/tv_continue"
        android:visibility="gone"
        app:layout_constraintTop_toBottomOf="@+id/tv_welcome"
        android:layout_marginTop="10dp"
        android:layout_marginEnd="@dimen/_20sdp"
        android:layout_marginStart="@dimen/_20sdp"
        app:layout_constraintLeft_toLeftOf="parent"
        android:text="Sign in to continue" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_marginTop="@dimen/_20sdp"
        android:layout_height="wrap_content"
        android:weightSum="1"
        android:layout_marginStart="@dimen/_20sdp"
        android:layout_marginEnd="@dimen/_20sdp"
        app:layout_constraintTop_toBottomOf="@+id/tv_continue"
        android:id="@+id/phone_layout"
        android:orientation="horizontal">

        <com.hbb20.CountryCodePicker
            android:layout_marginEnd="@dimen/_10sdp"
            android:layout_width="0dp"
            android:layout_weight="0.4"
            android:textSize="@dimen/_12sdp"
            android:id="@+id/countryCode"
            style="@style/smallText"
            android:background="@drawable/edittext_background"
            android:layout_height="match_parent" />

        <EditText
            android:layout_width="0dp"
            android:layout_weight="0.6"
            android:hint="Phone Number"
            android:inputType="number"
            style="@style/smallText"
            android:id="@+id/et_phone"
            android:maxLength="11"
            android:padding="@dimen/_10sdp"
            android:drawablePadding="10dp"
            android:drawableStart="@drawable/ic_phone"
            android:background="@drawable/edittext_background"
            android:layout_height="wrap_content" />
    </LinearLayout>

    <EditText
        android:layout_width="match_parent"
        android:layout_marginTop="@dimen/_10sdp"
        android:hint="Password"
        android:singleLine="true"
        android:drawablePadding="10dp"
        android:layout_marginEnd="@dimen/_20sdp"
        android:layout_marginStart="@dimen/_20sdp"
        app:layout_constraintTop_toBottomOf="@+id/phone_layout"
        app:layout_constraintLeft_toLeftOf="parent"
        android:padding="@dimen/_10sdp"
        style="@style/smallText"
        android:inputType="textPassword"
        android:id="@+id/et_password"
        android:drawableStart="@drawable/ic_lock"
        android:background="@drawable/edittext_background"
        android:layout_height="wrap_content" />

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="wrap_content"
        android:id="@+id/forgot_layout"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_marginBottom="@dimen/_15sdp"
        android:layout_height="wrap_content">

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/img_"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintRight_toRightOf="@+id/forgot_pass"
            app:layout_constraintLeft_toLeftOf="@+id/forgot_pass"
            android:src="@drawable/forgot_icon"
            android:layout_marginEnd="@dimen/_20sdp"
            android:layout_marginStart="@dimen/_20sdp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAllCaps="false"
            style="@style/smallText"
            android:layout_marginEnd="@dimen/_20sdp"
            android:layout_marginStart="@dimen/_20sdp"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/img_"
            android:layout_gravity="right"
            android:padding="@dimen/_5sdp"
            android:textColor="@color/grey_border"
            android:id="@+id/forgot_pass"
            android:layout_marginTop="8dp" />
    </androidx.constraintlayout.widget.ConstraintLayout>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/btn_signin"
        android:textAppearance="@style/textOnButton"
        android:text="Login"
        app:layout_constraintTop_toBottomOf="@+id/et_password"
        android:layout_marginEnd="@dimen/_20sdp"
        android:layout_marginStart="@dimen/_20sdp"
        android:layout_marginTop="@dimen/_30sdp"
        android:paddingLeft="5dp"
        />

        <ProgressBar
            android:id="@+id/pb"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:minHeight="50dp"
            android:minWidth="50dp"
            android:gravity="center"
            android:indeterminate="true"
            android:elevation="10dp"
            android:visibility="gone"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            android:indeterminateTintMode="src_atop"
            android:indeterminateTint="@color/orange"
            />

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

答:
Update following in the activity tag in your manifest:

android:windowSoftInputMode="adjustNothing"

Body:
There are two edittext on a screen and a button on bottom of the screen, the problem is when I click on edittext and keyboard open ups the button at the bottom appears above the keyboard, I want bottom buton to be at its original place rather than moving up with keyboard. the button is bottom aligned

Thanks

P.S:
I have tried adjust pan, resize etc nothing working

<activity
        android:screenOrientation="portrait"
        android:name=".activities.MainActivity"
        android:windowSoftInputMode="stateUnchanged|adjustResize"
        android:theme="@style/AppTheme"
     />

XML:

<androidx.constraintlayout.widget.ConstraintLayout
    android:id="@+id/linearLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/text_white"
    android:orientation="vertical"
    android:paddingTop="@dimen/_20sdp"
    android:elevation="5dp"
    tools:context=".fragments.login.LoginFragment">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/tv_welcome"
        android:layout_marginRight="@dimen/_40sdp"
        android:layout_marginStart="@dimen/_20sdp"
        app:layout_constraintLeft_toLeftOf="parent"
        android:maxLines="2"
        style="@style/headingText"
        android:text="Welcome to the World \nof PACKR" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAllCaps="false"
        android:id="@+id/tv_continue"
        android:visibility="gone"
        app:layout_constraintTop_toBottomOf="@+id/tv_welcome"
        android:layout_marginTop="10dp"
        android:layout_marginEnd="@dimen/_20sdp"
        android:layout_marginStart="@dimen/_20sdp"
        app:layout_constraintLeft_toLeftOf="parent"
        android:text="Sign in to continue" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_marginTop="@dimen/_20sdp"
        android:layout_height="wrap_content"
        android:weightSum="1"
        android:layout_marginStart="@dimen/_20sdp"
        android:layout_marginEnd="@dimen/_20sdp"
        app:layout_constraintTop_toBottomOf="@+id/tv_continue"
        android:id="@+id/phone_layout"
        android:orientation="horizontal">

        <com.hbb20.CountryCodePicker
            android:layout_marginEnd="@dimen/_10sdp"
            android:layout_width="0dp"
            android:layout_weight="0.4"
            android:textSize="@dimen/_12sdp"
            android:id="@+id/countryCode"
            style="@style/smallText"
            android:background="@drawable/edittext_background"
            android:layout_height="match_parent" />

        <EditText
            android:layout_width="0dp"
            android:layout_weight="0.6"
            android:hint="Phone Number"
            android:inputType="number"
            style="@style/smallText"
            android:id="@+id/et_phone"
            android:maxLength="11"
            android:padding="@dimen/_10sdp"
            android:drawablePadding="10dp"
            android:drawableStart="@drawable/ic_phone"
            android:background="@drawable/edittext_background"
            android:layout_height="wrap_content" />
    </LinearLayout>

    <EditText
        android:layout_width="match_parent"
        android:layout_marginTop="@dimen/_10sdp"
        android:hint="Password"
        android:singleLine="true"
        android:drawablePadding="10dp"
        android:layout_marginEnd="@dimen/_20sdp"
        android:layout_marginStart="@dimen/_20sdp"
        app:layout_constraintTop_toBottomOf="@+id/phone_layout"
        app:layout_constraintLeft_toLeftOf="parent"
        android:padding="@dimen/_10sdp"
        style="@style/smallText"
        android:inputType="textPassword"
        android:id="@+id/et_password"
        android:drawableStart="@drawable/ic_lock"
        android:background="@drawable/edittext_background"
        android:layout_height="wrap_content" />

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="wrap_content"
        android:id="@+id/forgot_layout"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_marginBottom="@dimen/_15sdp"
        android:layout_height="wrap_content">

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/img_"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintRight_toRightOf="@+id/forgot_pass"
            app:layout_constraintLeft_toLeftOf="@+id/forgot_pass"
            android:src="@drawable/forgot_icon"
            android:layout_marginEnd="@dimen/_20sdp"
            android:layout_marginStart="@dimen/_20sdp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAllCaps="false"
            style="@style/smallText"
            android:layout_marginEnd="@dimen/_20sdp"
            android:layout_marginStart="@dimen/_20sdp"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/img_"
            android:layout_gravity="right"
            android:padding="@dimen/_5sdp"
            android:textColor="@color/grey_border"
            android:id="@+id/forgot_pass"
            android:layout_marginTop="8dp" />
    </androidx.constraintlayout.widget.ConstraintLayout>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/btn_signin"
        android:textAppearance="@style/textOnButton"
        android:text="Login"
        app:layout_constraintTop_toBottomOf="@+id/et_password"
        android:layout_marginEnd="@dimen/_20sdp"
        android:layout_marginStart="@dimen/_20sdp"
        android:layout_marginTop="@dimen/_30sdp"
        android:paddingLeft="5dp"
        />

        <ProgressBar
            android:id="@+id/pb"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:minHeight="50dp"
            android:minWidth="50dp"
            android:gravity="center"
            android:indeterminate="true"
            android:elevation="10dp"
            android:visibility="gone"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            android:indeterminateTintMode="src_atop"
            android:indeterminateTint="@color/orange"
            />

</androidx.constraintlayout.widget.ConstraintLayout>


问:
Skipping NA rows in index column
I have a dataframe with a column with values TRUE and NA. I'd like to add an index column to the df that indexes all rows with TRUE but simply skips all rows with NA, without removing them. Like this:

```<code>VarA    ID
TRUE    1
NA      NA
NA      NA
TRUE    2
TRUE    3
</code>```

At the moment I'm doing it as:

```<code>i = 1:nrow(df)
df$ID <- ifelse(df$VarA == TRUE, i, NA)
</code>```

but that gives me

```<code>VarA    ID
TRUE    1
NA      NA
NA      NA
TRUE    4
TRUE    5
</code>```

which is not what I want. I know this should be super easy with something like na.omit but somehow I just can't figure it out.

答:
Using base R</p>

```<code>df1$ID2[!is.na(df1$VarA)] <- seq_along(na.omit(df1$VarA))

  VarA ID ID2
1 TRUE  1   1
2   NA NA  NA
3   NA NA  NA
4 TRUE  2   2
5 TRUE  3   3
</code>```

Title: Skipping NA rows in index column

Body:
I have a dataframe with a column with values TRUE and NA. I'd like to add an index column to the df that indexes all rows with TRUE but simply skips all rows with NA, without removing them. Like this:

VarA    ID
TRUE    1
NA      NA
NA      NA
TRUE    2
TRUE    3

At the moment I'm doing it as:

i = 1:nrow(df)
df$ID <- ifelse(df$VarA == TRUE, i, NA)

but that gives me

VarA    ID
TRUE    1
NA      NA
NA      NA
TRUE    4
TRUE    5

which is not what I want. I know this should be super easy with something like na.omit but somehow I just can't figure it out.

Body:
Using base R

df1$ID2[!is.na(df1$VarA)] <- seq_along(na.omit(df1$VarA))

  VarA ID ID2
1 TRUE  1   1
2   NA NA  NA
3   NA NA  NA
4 TRUE  2   2
5 TRUE  3   3


答:
data.table solution

```<code>library( data.table )
DT <- data.table::fread("
VarA
TRUE
NA
NA
TRUE
TRUE")

DT[ !is.na(VarA), ID := .I][]
</code>```

or

```<code>setDT(df)[ !is.na(VarA), ID := .I][]
</code>```

results in

```<code>#    VarA ID
# 1: TRUE  1
# 2:   NA NA
# 3:   NA NA
# 4: TRUE  2
# 5: TRUE  3
</code>```

Title: Skipping NA rows in index column

Body:
data.table solution

library( data.table )
DT <- data.table::fread("
VarA
TRUE
NA
NA
TRUE
TRUE")

DT[ !is.na(VarA), ID := .I][]

or

setDT(df)[ !is.na(VarA), ID := .I][]

results in

#    VarA ID
# 1: TRUE  1
# 2:   NA NA
# 3:   NA NA
# 4: TRUE  2
# 5: TRUE  3


答:
It's not the cleanest, but it seems to work :

I create spaces before the minus - in order to split later between numbers

I remove spaces for E -, because of a side effect of previous point

I remove the \n hard written in text with replace(" \\n", "")

I remove the "next line" characters too \n

and I remove the 11 first characters (ex: ADMAS) with [11:]

```<code>filename = "data.txt"
string_fnd_1 = "ADMAS"
textfile = open(filename, 'r')
file_lines = textfile.readlines()
textfile.close()
new_file_lines = []
for li in file_lines:
    new_line = li.replace("-", " -").replace("E -", "E-").replace(" \\n", "").replace("\n", "")[11:]
    if string_fnd_1 in li:
        new_file_lines.append(new_line)
matches_admas = [line.split() for line in new_file_lines]

print(matches_admas)
</code>```

Output :

```<code>[
    ['8.046E+03', '8.206E-03', '1.532E+04', '1.066E-01', '6.982E+06', '-2.820E+00'],
    ['-6.868E-03', '2.009E+05', '1.454E-02', '9.516E+05', '-1.209E+00', '6.058E+06'],
    ['1.543E+04', '9.179E-01', '1.459E+06', '5.463E+00', '3.918E+07', '-2.904E+01'],
    ['-2.267E-01', '9.537E+05', '3.902E+00', '3.071E+07', '-1.344E+02', '1.073E+08'],
    ['7.005E+06', '2.260E+01', '3.978E+07', '6.296E+01', '7.586E+09', '-2.125E+03'],
    ['1.093E+00', '6.052E+06', '-6.178E+00', '1.065E+08', '-1.416E+03', '1.941E+09']
]
</code>```

Title: convert values in text file to array in python

Body:
I have a text file data.txt which looks as such:

ADMAS      8.046E+03 8.206E-03 1.532E+04 1.066E-01 6.982E+06-2.820E+00 \n
ADMAS     -6.868E-03 2.009E+05 1.454E-02 9.516E+05-1.209E+00 6.058E+06 \n
ADMAS      1.543E+04 9.179E-01 1.459E+06 5.463E+00 3.918E+07-2.904E+01 \n
ADMAS     -2.267E-01 9.537E+05 3.902E+00 3.071E+07-1.344E+02 1.073E+08 \n
ADMAS      7.005E+06 2.260E+01 3.978E+07 6.296E+01 7.586E+09-2.125E+03 \n
ADMAS      1.093E+00 6.052E+06-6.178E+00 1.065E+08-1.416E+03 1.941E+09 \n
FAMP       3.824E+03 7.120E-02 1.848E+05 7.317E-01 5.406E+06 4.096E+00 \n
FEPS       9.039E+01 3.571E+02 2.838E+00 3.580E+02 4.098E+01 1.892E+02 \n

(etc. In a recurring pattern). I want to have only the ADMAS values and put them in a 6x6 array.
I tried the following:

filename = "data.txt"
string_fnd_1 = "ADMAS"
textfile = open(filename, 'r')
file_lines = textfile.readlines()
textfile.close()
matches_admas = [line for line in file_lines if string_fnd_1 in line]

I get the following:

['ADMAS      8.046E+03 8.206E-03 1.532E+04 1.066E-01 6.982E+06-2.820E+00\n', 'ADMAS     -6.868E-03 2.009E+05 1.454E-02 9.516E+05-1.209E+00 6.058E+06\n',....]

Now, I want to get rid of the string "ADMAS", convert the values to float and reshape into a 6x6 array. Does someone know how to do this? Help would be appreciated.

Body:
It's not the cleanest, but it seems to work :

I create spaces before the minus - in order to split later between numbers

I remove spaces for E -, because of a side effect of previous point

I remove the \n hard written in text with replace(" \\n", "")

I remove the "next line" characters too \n

and I remove the 11 first characters (ex: ADMAS) with [11:]

filename = "data.txt"
string_fnd_1 = "ADMAS"
textfile = open(filename, 'r')
file_lines = textfile.readlines()
textfile.close()
new_file_lines = []
for li in file_lines:
    new_line = li.replace("-", " -").replace("E -", "E-").replace(" \\n", "").replace("\n", "")[11:]
    if string_fnd_1 in li:
        new_file_lines.append(new_line)
matches_admas = [line.split() for line in new_file_lines]

print(matches_admas)

Output :

[
    ['8.046E+03', '8.206E-03', '1.532E+04', '1.066E-01', '6.982E+06', '-2.820E+00'],
    ['-6.868E-03', '2.009E+05', '1.454E-02', '9.516E+05', '-1.209E+00', '6.058E+06'],
    ['1.543E+04', '9.179E-01', '1.459E+06', '5.463E+00', '3.918E+07', '-2.904E+01'],
    ['-2.267E-01', '9.537E+05', '3.902E+00', '3.071E+07', '-1.344E+02', '1.073E+08'],
    ['7.005E+06', '2.260E+01', '3.978E+07', '6.296E+01', '7.586E+09', '-2.125E+03'],
    ['1.093E+00', '6.052E+06', '-6.178E+00', '1.065E+08', '-1.416E+03', '1.941E+09']
]