Is there any difference between ViewStub and View? - performance

I am new to Android Development.
I read about ViewStub from https://developer.android.com/training/improving-layouts/loading-ondemand.html
It mentions that it is cheap and less memory to use it.
I have the following:
MainLayout.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/Layout1"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:background="#color/blue"
android:orientation="vertical" >
.....
.....
<Button android:id="#+id/ShowBackground"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
<Button android:id="#+id/ShowBackground2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="#string/title_close" />
<View
android:id="#+id/ShowView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#color/blue" />
<ViewStub
android:id="#+id/ShowViewStub"
android:layout="#layout/test"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
</RelativeLayout>
test.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/ShowViewLayout"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:background="#color/blue_dimmer"
android:orientation="vertical" >
</RelativeLayout>
MainActivity:
private ViewStub mViewStub;
private View mView;
private Button mBackground1;
private Button mBackground2
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.MainLayout);
mView = (ViewStub) findViewById(R.id.ShowView);
mViewStub = (ViewStub) findViewById(R.id.ShowViewStub);
mBackground1 = (Button)this.findViewById(R.id.ShowBackground);
mBackground1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mView.setVisibility(View.VISIBLE);
}
});
}
mBackground2 = (Button)this.findViewById(R.id. ShowBackground2);
mBackground2.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mViewStub.setVisibility(View.VISIBLE);
}
});
}
Questions:
View and ViewStub are working fine in the MainActivity.
I do understand ViewStub is good for the view that is rarely used.
If ViewStub is called at least 1 time in the MainActivity, shouldn't it be more memory usage since the test.xml layout is added to the activity?
As I can see is that ViewStub is always visible unless it is called View.Gone....
Can someone please explain what the differences between the two?
I greatly appreciate for your help,
Thank you.

The < include /> will just include the xml contents in your base xml file as if the whole thing was just a single big file. It's a nice way to share layout parts between different layouts.
The < ViewStub /> is a bit different because it is not directly included, and will be loaded only when you actually use it/need it, ie, when you set its visibility to VISIBLE (actually visible) or INVISIBLE (still not visible, but its size isn't 0 anymore). This a nice optimization because you could have a complex layout with tons of small views or headers anywhere, and still have your Activity load up really fast. Once you use one of those views, it'll be loaded.

Related

a personal adapter error with observer pattern

I have a problem with my personal adapter. When I search through the Observer pattern for information in a local database, it brings me the records but the adaptare is not called until you make a second attempt to delete and add the same petra to search. If I change the letter I have to delete it and re-enter it a second time so that it shows the help as you see in the image.
If you could help me I would appreciate it.
First search
enter image description here
second search. I delete the letter and enter it again
enter image description here
as you can see, now it works correctly.
I don't understood why.
Function call observer:
fun searchCountry(cadena:String){
var chain_1 = ""
if(cadena.trim().isNullOrEmpty()){
chain_1 = ""
}else{
chain_1 = cadena.trim() + "%"
}
locationViewModel.locationSearch(chain_1)
locationViewModel.locations.observe(this, Observer { locationList ->
autoCompleteTextView.setAdapter(LocationAdapter(this,locationList as List<Location>))
})
}
VieModel:
#HiltViewModel
class LocationViewModel #Inject constructor(private val getLocationUserCase: GetLocationUseCase) : ViewModel() {
val locations = MutableLiveData<List<Location?>>()
fun locationSearch(chain:String){
viewModelScope.launch {
val locationLst: List<Location> = getLocationUserCase(chain)
if(!locationLst?.isNullOrEmpty()){
locations.postValue(locationLst)
}else{
}
}
}
}
Adapter:
class LocationAdapter(context: Context, locations: List<Location>) : ArrayAdapter<Location>(context, 0, locations) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val view = convertView ?: LayoutInflater.from(context).inflate(R.layout.account_frg_user_create_location_items, parent, false)
getItem(position)?.let { location ->
view.findViewById<TextView>(R.id.txtCountry).apply {
text = location.nom_municipio
}
view.findViewById<TextView>(R.id.txtProvince).apply {
text = location.nom_provincia
}
}
return view
}
}
XML-adapter:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="match_parent"
android:maxHeight="56dp"
android:padding="16dp"
android:layout_height="wrap_content">
<TextView
android:id="#+id/txtCountry"
android:layout_width="match_parent"
android:layout_weight="1"
android:textAppearance="#style/TextAppearance.MaterialComponents.Body1"
android:layout_height="wrap_content"
tools:text="Pueblo" />
<TextView
android:id="#+id/txtProvince"
android:layout_width="match_parent"
android:layout_weight="1"
android:textAppearance="#style/TextAppearance.MaterialComponents.Body2"
android:gravity="end"
android:layout_height="wrap_content"
tools:text="Provincia" />
</LinearLayout>
XML-Autocomepletetextview:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<AutoCompleteTextView
android:id="#+id/autoCompleteTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=""
android:completionThreshold="1"
android:imeOptions="actionDone"
android:inputType="text"
/>
</LinearLayout>
It is expected that when I enter a letter for the first time, it will show the search help that does show if I delete and add the same letter again or enter two letters or more.
Finally, I found my mistake. What happened is that the component, AutoCompleteTextView, already performed the same function that it was doing with the addTextChangedListener, so it searched for the information on both sides. Finally, the solution is to remove the addTextChangedListener, and pass the complete list to the adapter, since it is the autocomplete that is in charge of carrying out the search that it did on the database.
fun iniciacilarBd(){
locationViewModel.locationSearch("%")
// <!-- BASE_DE_DATOS
locationViewModel.locations.observe(this, Observer { locationList ->
locations = locationList
LocationAdapter(this,locations).also { locationAdapter ->
autoCompleteTextView.setAdapter(locationAdapter)
}
})
}
Thanks for the help

Splash Screen with images and texts for Xamarin Android

I need create a background and then on top of that the text boxes and images as Splash Screen. What my steps?
You could use two activities. One activity is used to show the splash screen and the other used to show the mian activity.
splashscreen.xml:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="#drawable/star"/>
<TextView
android:text="Splash Screen Star"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
SplashScreen_Activity:
public class SplashScreen_Activity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.splashscreen);
// Create your application here
}
protected override void OnResume()
{
base.OnResume();
Task startupWork = new Task(() => { SimulateStartup(); });
startupWork.Start();
}
// Simulates background work that happens behind the splash screen
async void SimulateStartup()
{
await Task.Delay(3000); // Simulate a bit of startup work.
StartActivity(new Intent(Application.Context, typeof(Activity5)));
}
}
Activity5 is the main activity i want to show. You could load the layout in Activity5.
I really don't understand why you would be advising a user to use such an outdated technique of suggesting the use of SplashScreen Activity, for a splash screen when obviously there are far better techniques of achieving a SplashScreen. You are offering a solution that was even frowned upon back in 2016-16, let alone 2022.

WearableActionDrawer peek view does not hide

I'm trying to use WearableActionDrawer in my app. Previously I was using 'com.google.android.support:wearable:2.0.0-alpha1' and my layout looks like this:
<?xml version="1.0" encoding="utf-8"?>
<android.support.wearable.view.drawer.WearableDrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:rectLayout="#layout/rect_activity_main"
app:roundLayout="#layout/round_activity_main"
tools:context="com.example.grant.wearableclimbtracker.MainActivity"
tools:deviceIds="wear">
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id = "#+id/content_frame">
<android.support.wearable.view.GridViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.NestedScrollView>
<android.support.wearable.view.drawer.WearableNavigationDrawer
android:id = "#+id/top_navigation_drawer"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:background="#color/dark_grey"/>
<android.support.wearable.view.drawer.WearableActionDrawer
android:id="#+id/bottom_action_drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/grey" />
</android.support.wearable.view.drawer.WearableDrawerLayout>
After I switched to 'com.google.android.support:wearable:2.0.0' the behavior changed. The action drawer used to stay out of view until I swiped up to reveal the action menu, but now there is a peek view of the drawer that doesn't go away unless I open the menu and select something. Is this the intended behavior? It takes up a lot of real-estate:
Any advice would be much appreciated.
It was as I suspected, when NestedScrollingChild height matched the parentview, the action drawer peeks. The only way I could get it to hide was to increase the NestedScrollingChild view by 1dp:
// get the screen width
DisplayMetrics metrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
// set height of framelayout to be slightly larger than view
mSessionLayout = rootView.findViewById(R.id.sessionLayout);
mSessionLayout.setMinimumHeight(metrics.heightPixels+1);

ProgressBar multiple displaying

I have an AsyncTask linked to a refresh Button (when I click on my refresh button my AsyncTask is called).
I have on my Layout a LinearLayout field for my ProgressBar :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#color/grey">
<Button android:id="#+id/refresh_p"
android:text="#string/refresh_promo"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/custom_button1"/>
<LinearLayout android:id="#+id/linearlayoutProgressBar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"/>
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:listSelector="#color/tabTransparent"
android:cacheColorHint="#00000000"/>
<!-- <ListView android:id="#+id/list_promo"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>-->
</LinearLayout>
In my AsyncTask :
#Override
protected void onPreExecute()
{
super.onPreExecute();
pb = new ProgressBar(context);
LinearLayout ll = (LinearLayout) ((Activity) context).findViewById(R.id.linearlayoutProgressBar);
ll.addView(pb);
pb.setVisibility(View.VISIBLE);
}
#Override
protected void onPostExecute(ArrayList<HashMap<String, String>> promoList)
{
...
if (pb!=null)
{
pb.setVisibility(View.GONE);
((LinearLayout)pb.getParent()).removeView(pb);
}
}
The problem I have is when I make more than 2 clicks on my Refresh Button then Multiple ProgressBar are displaying into the screen.. I just want that the new ProgressBar replace the old at the same position ..
My guess is that you are probably starting your AsyncTask in a manner similar to this:
new RefreshTask().execute(params);
Instead of that, create an instance variable in your activity. Let's say this is named mTask and substitute the above code for the following call:
if(mTask != null && mTask.getState != AsyncTask.State.RUNNING){
mTask = new RefreshTask();
mTask.execute(params);
}
This way you will ensure that only one instance of your task is running at a given time and the user will have to wait until the refresh is finished before he can start a new refresh.
If you want the user to be able to cancel an existing refresh task and run a new one, you will have to cancel the old one before starting a new one:
if(mTask != null){
if(mTask.getStatus() == AsyncTask.Status.RUNNING){
mTask.cancel(true);
}
mTask = new RefreshTask();
mTask.execute(params);
}
This way the old task and it's ProgressBar will be properly replaced by the new one.

Not able to set the background to a ListView

I am trying to set background for my List view . I have taken a image from the drawable and set it as background to the layout file then it is giving the result as following screen shot
and when i just remove the background am getting the thing which i required but no background.
and screen shot is
Is there is any other Syntax to set background for ListView.
And my Code for layout is
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView android:text="#+id/TextView01" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="#+id/label"
android:textColor="#FF0000"
android:textSize="30px"></TextView>
</LinearLayout>
And my java code and that is
String[] names = new String[] { "India", "Malaysia" };
// Use your own layout and point the adapter to the UI elements which
// contains the label
this.setListAdapter(new ArrayAdapter<String>(this, R.layout.screen3,
R.id.label, names));
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
// Get the item that was clicked
Object o = this.getListAdapter().getItem(position);
String keyword = o.toString();
if(keyword.equals("India"))
{
Intent ima1=new Intent(screen3.this,new21.class);
startActivity(ima1);
}
else
{
Intent ima2=new Intent(screen3.this,new22.class);
startActivity(ima2);
}
Toast.makeText(this, "You selected: " + keyword, Toast.LENGTH_LONG)
.show();
}
And lastly i need is I want the background image with proper listview showing one listitem after another. Thanks in advance
}
Try this code, Instead of extending ListActivity you can set layout that contains List View and separate layout for contents of List View.
Java Code :
public class Table_Layout extends Activity {
ListView list_view;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.table_layout);
list_view=(ListView)findViewById(R.id.list_view);
String[] names = new String[] { "India", "Malaysia" };
list_view.setAdapter(new ArrayAdapter<String>(this, R.layout.screen3,R.id.label, names));
}
}
Main XML that contains List View :table_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:background="#drawable/uploading">
<ListView android:layout_width="fill_parent" android:layout_height="fill_parent"
android:id="#+id/list_view"
/>
Then Contents of List View :screen3.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<TextView android:text="#+id/TextView01" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="#+id/label"
android:textColor="#FF0000"
android:textSize="30px"></TextView>
</LinearLayout>
Set you Background for the table_layout.xml so that it will applied for entire List View as you expected.
All looks well with your xml file. Try implementing the below mentioned:-
Make an image of the size you want your listview's each row of. And set it as the parent LinearLayout's background. Set:- android:layout_width="fill_parent" android:layout_height="wrap_content".
Hope this helps !! :)

Resources