czwartek, 27 listopada 2014

iOS, a co to jest - odcinek pierwszy: Objective-C

Przychodzi czas, kiedy muzyk rockowy nasyci się muzyką rock  i zaczyna sięgać po interpretacje klasyków czy choćby utworów z lat pięćdziesiątych ubiegłego wieku, na które wcześniej nawet by nie spojrzał.  W żadnym razie nie chodzi o porzucenie głównego nurtu, który go zasadniczo wyraża, ale o poszerzenie horyzontów, poszukiwanie nowych form, które również mogą wpłynąć inspiracyjnie na zasadniczo grany gatunek muzyczny.  Nie wiem ile takich przypadków zdarza się w IT, ale spotyka się czasami osoby, które potrafią wyjść poza swoje ortodoksyjne czasami wręcz religie. Inna jeszcze sprawa że również trendy światowe w ostatnich latach mają pewne zakręty, daje się niewątpliwie odczuć pewien przesyt wysokopoziomowych rozwiązań .NET czy Java, mamy renesans znanych od dawna technologii Web, w których dostrzeżono platformę do budowania całych aplikacji.  Kolejnym zakrętem jest niewątpliwie rozwijanie Visual Studio w kierunku wspierania narzędzi i rozwiązań Open Source czy wszystkich platform mobilnych, zamiast wyłącznie własnej.  iOS to jak jeden z ostatnich niepoznanych lądów, do którego chciałem dopłynąć już jakiś czas temu, by dopełnić pojęcia o platformach mobilnych, porównać rozwiązania Apple z Windows/Windows Phone oraz Android. Owszem mamy takie rzeczy jak Apache Cordova czy Xamarin, ale dziś i przez najbliższy czas cofnę się do “lat pięćdziesiątych”, bo taką mam ochotę. Niech będzie trochę hardcoru z tamtych lat! Czy będzie to tylko przeszłość?  Objective-C zyskał co prawda następcę w postaci Swift, ale miejscami nawiązuje on czasami do niego, od czegoś trzeba zacząć, a rozwiązania natywne zawsze będą najlepiej wyrażały user experience danej platformy i będą najbardziej wydajne.  Xamarin ma pełne pokrycie w API, ale czasami dobrze znać tam natywny interfejs użytkownika, a Cordova jest nowoczesna, ale nadal rozwiązania Web wciąż mogą ustępować rozwiązaniom natywnym (chociaż je gonią z roku na rok i stają się coraz wydajniejsze) i nie są kompletne (wymagają pisania natywnych wtyczek, przy tworzeniu własnych znajomość danej natywnej platformy jest niewątpliwie potrzebna)

Dziś tylko krótko spisałem sobie podstawy podstaw samego języka Objective-C, jeszcze bez iOS.  Byłem nastawiony na hardcore połączony z rozwiązywaniem łamigłówek. Na razie mogę powiedzieć, że owszem składnia jest momentami zupełnie inna od C#, VB, C++, Java, JavaScript, ale… może się podobać, po zapoznaniu się z nią jest całkiem – przynajmniej jak na razie – zrozumiała. Mamy odpowiedniki przynajmniej podstawowych konstrukcji z C++, C# czy Java, język wydaje się…  przyjaźniejszy od czystego JavaScript ECMA 5.  Ma klasy, interfejsy, dziedziczenie które dopiero teraz zaczynają wchodzić w JavaScript. Objective-C ma też pewną dynamiczność, którą wprowadzono do C# w 2010 roku. Archaizmem jest może - jak na razie - tylko ręczne alokowanie pamięci czy niszczenie obiektów oraz brak typu enum (używamy makra #define) oraz typu bool (jest predefiniowane makro dla int).  To na razie początki, zobaczymy co będzie dalej.

 

Historia

  • 1980 - powstanie, kompatybilny z C i zorientowany obiektowo, inspiracja Smalltalk
  • 1988 - NeXT
  • 1996 - Apple

Ogólne właściwości

  • nadzbiór C
  • oparty o wiadomości  (odpowiednik metod jak w SmallTalk)
  • separacja interfejsu od implementacji (dwa pliki *.h i *.m lub dwie sekcje)
  • dynamiczne typowanie
  • mixiny
  • wskaźniki
  • zarządzanie pamięcią

XCode

Hello World

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])

{

         @autoreleasepool {

                   NSLog(@”Hello, World!”);   //@ – string

          }

          return 0;

}

 

Zmienne i operatory

Zmienne

Wszystkie posiadają typ

4 podstawowe typy:

  • int
  • float
  • double
  • char

Rozmiary zależą od systemu operacyjnego

Nie ma typu boolean, jest makro BOOL (inna nazwa dla FALSE = 0 i TRUE = 1)

kwalifikatory:

  • long
  • long long
  • short
  • unsigned
  • signed

Typ id

  • dowolny typ
  • umożliwia polimorfizm i dynamiczny binding

NSString

int x = 41;

int x = TRUE;

x = (1 == 4);

NSLog(@”Ala ma kota nr %i”, x);

%i - int

%f - float, double   (zmienna float 78.6 zostanie wypisana jako 78.599998 !  double dokładnie)

char c = ‘a’;

%c - char

Odczyt z linii komend:

scanf(%i”, &x);

NSString *name = @”Marcin”;

NSLog(@”Na imię mam %@”, name);

Zakresy:

definicja jest brana z lokalnego bloku, jak nie ma definicji to brana jest z bloku nadrzędnego itd.

Operatory

  • -
  • *
  • /
  • +
  • %

Przypisanie

  • =
  • +=
  • -=
  • *=
  • /=
  • %=
  • ++
  • --

Porównanie

  • ==
  • >
  • >=
  • <
  • <=
  • !=
  • &&
  • ||
  • !

Kompletny zbiór operatorów z C

Stałe

extern const int COUNT;

const int COUNT = 5;

lub

#define COUNT 5

 

Klasy

Interfejs

  • definiuje dane
  • opisuje metody
  • inny niż interfejs w Javie lub C#
  • plik .h

Implementacja

  • definicja metod
  • plik .m

Obiekty

  • tworzenie
    • Alloc - alokacja pamięci
    • Init - inicjalizacja, jak konstruktor
  • niszczenie
    • Release - zwolnienie pamięci
    • Dealloc - wywołanie na obiekcie, który nie ma już referencji, jak destruktor

Metody i wiadomości

Klasy mają metody i wysyłają wiadomości

Klasa może odpowiedzieć na wiadomość, nawet jeśli nie definiuje metody

//deklaracja

//- object, + klasa;  typ zwracany; nazwa metody; typ I parametru; nazwa I parametru; nazwa drugiego parametru, typ drugiego parametru, zmienna, do której trafia drugi parametr

//nazwa II parametru,

-(int) add: (int) first and: (int) second; 

//użycie

[myClass  add:1  and:2]

Przykładowa klasa:

plik S.h

@interface S:  NSObject

{

         int size;

}

-(void)x:  (int)s;

-(int)getY;

@end

      

plik  S.m

@implementation S

-(void)x: (int)s

{

         size = s;

}

-(int) getY

{

        return size * size;

}

@end

 

użycie

@autoreleasepool

{

         S *s = [[S alloc] init];   //alokacja i domyślna inicjalizacja

         [s x:3];  //wysłanie wiadomości

         int a = [s getY];

}

 

własny inicjalizator

@interface S: NSObject

{

         …

}

-(id)initWithS: (int)s;

@end

 

@implementation S

-(id)initWithS: (int)s

{

         self = [super init];

         if (self)

         {

                  [self setY:s];

         }

         return self;

}

@end

 

S *s = [[S alloc] initWithS:10];

 

propercje

@interface S: NSObject

{

}

@property int x;

@end

 

@implementation S

@synthesize x;

 

       S *s = [[S alloc] initWithS:10];

       int b = s.x;

      

Kontrola

Warunki

@interface Sc : NSObject

-(S *) bigger: (S *) s1  and: (S *) s2;

@end

 

@implementation Sc

-(S *) bigger: (S *) s1  and: (S *)s2

{

         if([s1 getY] > [s2 getY])

         {

                  return s1;

         }

         else

         {

                  return s2;

         }

}

@end

“Wyliczenie”

#define GREEN 1

#define BLUE 2

#define RED3

 

-(NSString *)printC

{

           switch(c)

           {      

                    case  GREEN :

                           return @”Green”;

                           //break;

                    default:

                           return @””;

                           //break;

           }

}

Iteracje

Pętla for

for (int i = 0;  i < 5; i++) 

{

}

Pętla while

int i = 1;

while (i < 5)

{

          if (i == 4)

                  break;  //continue;

          i++;

}

Wyrzucenie wyjątku

@throw [NSException exceptionWithName: @”Invalid …”  reason: @”…”  userInfo: nil ];

Łapanie:

@try {

}

@catch  (NSException *exception)  {

}

@finally {

}

 

Dziedziczenie i polimorfizm

Dziedziczenie

  • wszystkie klasy dziedziczą po NSObject
  • pojedyncze
  • deklarowane w interfejsie

@interface S : NSObject

-(int) getA;

@end

 

@implementation S

-(int)getA

{

         return -1;

}

@end

 

@interface T: S

@end

 

@implementation T

-(int)getA

{

         return 41;

}

@end

Polimorfizm

  • inny niż w wielu językach
  • może używać id do reprezentowania każdego typu
  • każda wiadomość może być przekazana do każdego obiektu

id object = [[T alloc] init];

NSLog(@”%i”, [object getA]);   //dynamiczne wywołanie

Można skompilować kod z wywołaniem wiadomości, która nie jest zdefiniowana w typie obiektu. Sprawdzanie następuje w runtime, jak coś jest w rzeczywistym typie obiektu to zostanie wywołane, jak nie ma poleci wyjątek.

niedziela, 23 listopada 2014

Pojedynek z Androidem - odc. 17 (ost) Fragmenty (uzupełnienia)

Po pewnej przerwie udało mi się napisać ostatni post z cyklu o Android (przynajmniej na jakiś czas).

Kilka słów komentarza do pewnych “odkryć”:

tranzakcje - zmiany w UI rejestrowane są jako tranzakcje, co więcej możemy je dodać do stosu back, co pozwala nam symulować zmianę stanu tej samej aktywności, jakby to była nawigacja pomiędzy różnymi ekranami.  Brawo! Takiego gotowego API nie widziałem jeszcze na platformach znanych przeze mnie wcześniej.

fragmenty - było już o nich zdaje się niejeden już raz, mam mieszane uczucia co do niektórych rozwiązań. Np. widział ktoś by onClick w XML fragmentu nie mógł działać jak należy, tylko próbował coś wywoływać na aktywności?   Podobnie opakowywanie obiektów wizualnych w klasy fragmentów wydają się komplikacją (np. Dialog w DialogFragment). Pewnie wynika to z zaszłości, kiedy nie było fragmentów… Cykl życia fragmentu w aktywności też jest dość złożony. Obfituje w sporą liczbę callbacków, trzeba wiedzieć, co wywoła się w jakiej kolejności we fragmencie, a co w aktywności. Owszem mamy może pewną optymalizację dla wydajności przy wpinaniu i wypinaniu fragmentu do aktywności, ale mam wrażenie jakby użytkownik platformy poznawał jej trzewia, rozróżniając trzy stany istnienia fragmentu. Aha, nieobowiązkowe nadpisywanie layoutu w niektórych miejscach własnymi zasobami XML kojarzy mi się z kontrolkami XAML obsługującymi szablony. Powiązania fragmentu z ActionBar też czasami dość przekombinowane, a nawigacja wg. listy dropdown czy zakładek wymaga sporo powtarzającego się za każdym razem kodu.

 

Podstawy

Zastosowania

  • adaptatywność UI
  • zakładki
  • okna dialogowe
  • customizacja ActionBar

Obsługa kliknięcia przycisku we fragmencie

  • onClick  - handler musiałby być w aktywności
  • implementacja interfejsu OnClickListener na klasie fragmentu + jawne powiązanie fragmentu z każdym przyciskiem - lepiej

public class XFragment extends Fragment implements View.OnClickListener {

         …

         @Override

         public View onCreateView(…) {

                 …

                 Button button = (Button) theView.findViewById(R.id.button1);

                 button.setOnClickListener(this);

                 return theView;

         }

         public void myButtonClickHandler(View view) {                

         }

         public void onClick(View view) {

                  myButtonClickHandler(view);

         }

}

 

Tranzakcje fragmentów

Fragmenty mogą być dynamicznie zarządzane przez aktywność

  • zmiany w UI bez opuszczania aktywności
  • FragmentTransactions - wszystkie zmiany muszą zachodzić w tranzakcji

FragmentManager fm = getFragmentManager();

FragmentTransaction ft = fm.beginTransaction();

ft.commit();

Dynamiczne dodawanie fragmentów do aktywności

  • tworzymy instancję fragmentu
  • występują wszystkie callbacki fragmentu przy inicjalizacji/wyświetlaniu
  • równoważne z <fragment> w layout

XFragment frag = new XFragment();

FragmentManager fm = getFragmentManager();

FragmentTransaction ft = fm.beginTransaction();

ft.add(R.id.myGroup, frag, “xxxtag”);

ft.commit();

Dynamiczne usuwanie fragmentów z aktywności

  • potrzebujemy referencji na usuwany fragment (FragmentManager.findFragmentByTag/findFragmentById)
  • instancja usuniętego fragmentu nie może być już używana w aktywności

ft.remove(frag);

Zastępowanie fragmentów

  • działa z ViewGroup

YFragment diffFrag = new YFragment();

FragmentManager fm = getFragmentManager();

FragmentTransaction ft = fm.beginTransaction();

ft.replace(R.id.myGroup, diffFrag);

ft.commit();

Trzy rozłączne poziomy egzystencji fragmentu

  • obiekt Java
  • powiązanie z aktywnością
  • wyrenderowane UI

Attach/Detach

UI fragmentu może być zarządzane niezależnie od relacji z aktywnością

  • Użyteczne dla częstego przesuwania fragmentów (unikamy narzutu pełnego demontowania i ustawiania)
  • FragmentTransaction.detach(fragment)
    • demontaż UI
    • instancja fragmentu pozostaje nienaruszona i powiązana z aktywnością (można też nadal ją wyszukać przez FragmentManager)
    • otrzymywane callbacki:  onPause, onStop, onDestroyView
    • nieotrzymywany callback:  onDetach
  • FragmentTransaction.attach(fragment)
    • rekonstrukcja UI
    • otrzymywane callbacki:  onCreateView, onActivityCreated, onStart, onResume
    • nieotrzymywany callback:  onAttach

Tranzakcje fragmentów i przycisk back

  • domyślnie tranzakcje nie są świadome przycisku back
  • tranzakcje mogą być umieszczone na stosie back
    • addToBackStack tworzy nowy wpis (można wrócić do poprzedniego stanu naciskając back)
    • musi to być wywołane przed zatwierdzeniem tranzakcji
    • opcjonalnie możemy dołączyć nazwę dla wspisu

ft.addToBackStack(“ScreenX”);   //jeśli chcemy programowo cofnąć się do tego wpisu

Programowa nawigacja po stosie back

  • FragmentManager.popBackStack()  - symulacja naciśnięcia back
  • FragmentManager.popBackStack z nazwą ekranu - powrót do danej tranzakcji

fm.popBackStack(“ScreenX”, 0);   //powrót do wskazanego ekranu

fm.popBackStack(“ScreenX”, POP_BACK_STACK_INCLUSIVE);   //powrót do ekranu poprzedzającego wskazany

Dostęp do stosu back za pomocą FragmentManager

  • notyfikacje o zmianach w stosie
    • implementujemy interfejs Fragment.OnBackStackChangedListener
    • przekazujemy implementację do addBackStackChangedListener
  • dostęp do wpisów stosu
    • getBackStackEntryCount - liczba wpisów
    • getBackStackEntryAt(index)  - pobranie wpisu o podanym index (na szczycie:  getBackStackEntryCount() - 1)

public class XActivity extends Activity implements FragmentManager.OnBackStackChangedListener  {

         …

         @Override

         public void onCreate(…)  {

                …

                FragmentManager fm = getFragmentManager();

                fm.addOnBackStackChangedListener(this);

         }

         …

         public void onBackStackChanged()  {               

         }

}

 

Cykl życia fragmentów i specjalizacja

inicjalizacja:

  • callbacki cyklu życia takie jak dla aktywności
    • onCreate, onStart, onResume
    • każdy callback aktywności wołany przed callbackiem fragmentu o tej samej nazwie
  • callbacki specyficzne dla ustawienia/wyświetlenia fragmentu
    • onAttach - otrzymuje referencję na aktywność, która zawiera fragment
    • onCreateView
    • onActivityCreated - zakończenie tworzenia aktywności zawierającej fragment
  • callbacki aktywności dla ustawienia fragmentu
    • onAttachFragment - za każdym razem, gdy fragment jest wpinany do aktywności
  1. Activity: onCreate    
  2. Fragment: onAttach
  3. Activity: onAttachFragment
  4. Fragment: onCreate
  5. Fragment: onCreateView
  6. Fragment: onActivityCreated
  7. Activity: onStart
  8. Fragment: onStart
  9. Activity: onResume
  10. Fragment: onResume

dla każdego fragmentu:  2-5

demontaż:

  • callbacki znane z aktywności
    • onPause, onStop, onDestroy
    • każdy callback aktywności wywoływany po callbacku o takiej samej nazwie
  • callbacki specyficzne dla niszczenia fragmentu
    • onDestroyView - widok zwracany przez onCreateView nie jest już przypięty do fragmentu
    • onDetach - fragment nie jest już przypięty do widoku

Rodzaje fragmentów

  • Fragment
  • ListFragment
  • WebViewFragment
  • DialogFragment

ListFragment

  • automatyczne wyświetlenie danych z ListAdapter
    • SimpleAdapter - dla tablic i podobnych (np. ArrayAdapter)
    • SimpleCursorAdapter - dla danych używających kursora
  • przy domyślnym layout nie ma potrzeby nadpisywania onCreateView
    • ListFragment dostarcza domyślny widok

Definiowanie layoutu dla elementów listy

Modyfikacja wyglądu listy

  • definicja layout przy pomocy zasobu
    • umieszczenie ListView z id android:list
    • opcjonalne umieszczenie TextView z id android:empty
  • załadowanie layoutu w onCreateView

<LinearLayout …>

       <ListView android:id=”@id/android:list”  … />

       <TextView android:id=”@id/android:empty” …/>

</LinearLayout>

WebViewFragment

  • wrapper na WebView
  • niewielka własna funkcjonalność
    • getWebView() - dostęp do zawartego w sobie WebView

public class XWebFragment extends WebViewFragment  {

         …

         public void onActivityCreated(…)  {

                 …

                 WebView webView = getWebView();

                 webView.loadData(htmlString, “text/html”, null);

         }

}

DialogFragment

  • możliwość podania w onCreateView własnego layout przez zasób
  • wyświetlenie za pomocą metody show
    • będzie wewnętrznie zarządzać tranzakcją fragmentów, jeśli zostanie przekazany FragmentManager
    • może być zmiksowany jako część zarządzanej przez aplikację tranzakcji fragmentów
      • musi być wywołana jako ostatnia w tranzakcji, ponieważ wewnętrznie wywołuje commit
  • używanie styli i tematów
    • ustawienie musi się odbyć w onCreate
    • setStyle
      • style
        • STYLE_NORMAL - domyślna ramka z tytułem
        • STYLE_NO_TITLE - domyślna ramka bez tytułu
        • STYLE_NO_FRAME - brak domyślnej ramki i tytułu, onCreateView tworzy layout
        • STYLE_NO_INPUT - tak jak STYLE_NO_FRAME, ale nie otrzymuje wejścia
      • tematy pochodzą ze standardowych zasobów
        • android.R.style.Theme_Holo
          • android.R.style.Theme_Holo_Light_Dialog
  • obiekt Dialog jest automatycznie tworzony
    • dostępny za pomocą metody getDialog() 
      • tworzony jest przed callbackiem onCreateView (możemy wywołać tam getDialog())
    • dostępna jest większość zachowań Dialog
      • setTitle(“xxx”)
      • setCancelableOnTouchOutside(false) - każde wejście idzie do dialogu
  • istniejące klasy Dialog mogą być opakowane w DialogFragment
    • nadpisanie callbacka onCreateDialog
      • wywoływany po onCreate i przed onCreateView
    • najczęściej używamy tego do opakowania wbudowanej klasy AlertDialog
  • może być używany jako normalny fragment
    • musi używać layout z onCreateView
    • onCreateDialog nie jest wywoływane
    • getDialog zwraca null

public class XDialogFragment extends DialogFragment implements View.OnClickListener  {

         @Override

         public View onCreateView(…)  {

                 View theView = inflater.inflate(R.layout.xdialogfragment, container, false);

 

                  View yesButton = theView.findViewById(R.id.btnYes);

                  yesButton.setOnClickListener(this);

                  yesButton.requestFocus();                 

                  …

                  return theView;

         }

         public void onClick(View view)  {

                  int viewId = view.getId();

                  switch(viewId)  {

                         case R.id.btnYes:

                                 break;

                          case R.id.btnNo:

                                 break;

                  }

                  dismiss();

         }

}

Wyświetlenie

FragmentManager fm = getFragmentManager();

XDialogFragment fragment = new XDialogFragment();

// fragment.show(fm, “XDialog”)

 

FragmentTransaction ft = fm.beginTransaction();

fragment.show(ft, “XDialog”);

//nie wywołujemy commit  (dialog w środku sam wywołuje)

Opakowywanie innej klasy Dialog

public YDialogFragment extends DialogFragment  implements DialogInterface.OnClickListener {       

        public Dialog onCreateDialog(Bundle state)  {

                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

 

                builder.setMessage(“abc ?”);

                builder.setPositiveButton(“OK”, this);

                builder.setNegativeButton(“Cancel”, this);

 

                Dialog theDialog = builder.create();

                theDialog.setCanceledOnTouchOutside(false);

 

                return theDialog;

        }

        public void onClick(DialogInterface dialogInterface, int i)  {

                switch(i)  {

                        case Dialog.BUTTON_POSITIVE:

                                  break;

                         case Dialog.BUTTON_NEGATIVE:

                                  break;

                }

        }      

}

  Użycie jako standardowy fragment

  W onCreateView sprawdzamy czy getDialog nie zwraca null i wykonujemy operacje na obiekcie dialogu tylko jeśli jest.

FragmentManager fm = getFragmentManager();

XDialogFragment fragment = new XDialogFragment();

 

FragmentTransaction ft = fm.beginTransaction();

ft.add(android.R.id.content, fragment, “XDialog”);

ft.addToBackStack(“xxx”);

ft.commit();

 

Fragmenty i ActionBar

Opcje dodawane do ActionBar przez fragment

  • Metoda onOptionsItemSelected jest wywoływana najpierw w aktywności. Jeśli zwróciła ona false, to jest wywoływany jej odpowiednik na fragmencie.

Nawigacja pomiędzy różnymi fragmentami

  • lista - lista dropdown dostępnych fragmentów
  • zakładki - oddzielna zakładka dla każdego fragmentu, framework sam zarządza tranzakcjami

public class ActivityListNavigation extends Activity implements ActionBar.OnNavigationListener  {

        …

        public void onCreate(…)  {

               …

               String[] listMembers = { “option 1”, “option 2” };

 

               ActionBar actionBar = getActionBar();

               actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);

 

                ArrayAdapter<String> list = new ArrayAdapter<String>(this, R.layout.simple_spinner_dropdown_item, listMembers);

                actionBar.setListNavigationCallbacks(list, this);

        }

        public boolean onNavigationItemSelected(int i, long l)  {

                 Fragment fragment = null;

                  switch(i)  {

                          case 0:

                                    fragment = new Fragment1();

                                    break;

                           case 1:

                                    fragment = new Fragment2();

                                    break;

                  }

 

                  FragmentManager fm = getFragmentManager();

                  FragmentTransaction ft = fm.beginTransaction();

                  ft.replace(R.id.content, fragment);

                  ft.commit();

 

                  return true;

        }

}

public class ActivityTabbed extends Activity implements ActionBar.TabListener  {

         …

         Fragment _fragment1;

         Fragment _fragment2;

        

         public void onCreate(…)  {

                …

                ActionBar actionBar = getActionBar();

                actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);   

 

                createTab(actionBar, “xxx”);

                createTab(actionBar, “yyy”);           

         }        

         private void createTab(ActionBar actionBar, String displayName)  {

                 ActionBar.Tab newTab = actionBar.newTab();

                 newTab.setText(displayName);

                 newTab.setTabListener(this);

                 actionBar.addTab(newTab);

         }   

         public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction)  {

                  CharSequence displayName = tab.getText();                 

                   if (displayName.equals(“xxx”)) {

                           if (_fragment1 == null) {

                                   _fragment1 = new Fragment1();

                                  fragmentTransaction.add(R.id.content, _fragment1);

                           }

                           else  {

                                   fragmentTransaction.attach(_fragment1);

                           }

                   } else if (displayName.equals(“yyy”)) {

                   }

         }   

         public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction)  {

                   CharSequence displayName = tab.getText();

                   if(displayName.equals(“xxx”))  {

                            fragmentTransaction.detach(_fragment1);

                   } else if (displayName.equals(“yyy”)) {

                   }

         }  

         public void onTabReselected(ActionBar.Tab tab,  FragmentTransaction fragmentTransaction)  {

         }

}

sobota, 22 listopada 2014

Connect(); - część druga

Druga porcja nagrań, na które rzuciłem okiem.  Sporo interesujących nowości, z drugiej strony dużych zaskoczeń też nie ma.  C# 6 otrzymał różne składniowe udogodnienia skracające kod, jaki często piszemy na co dzień.  Czarnym koniem wydaje się Entity Framework 7, o którym stosunkowo niewiele się mówi, a to kolejna inicjatywa bycia na różnych platformach, a także na różnych rodzajach źródeł danych.

 

C++: Conformance And Cross-Platform Mobile Development

Prawie cały kod PowerPoint na Windows, OSX, Android, iOS jest napisany w przenośnym C++

image

 

Web Forms 4.6

Co nowego?

  • HTTP/2
  • Kompilatory Code DOM oparte na Roslyn
  • Async Model Binding

Pobieranie dużej ilości obrazków na stronie może być znacznie zoptymalizowane przy skorzystaniu z HTTP/2.  Wtedy zosoby mogą być pobrane równogle.

image

Aby na stronie używać właściwości z C#6 należy doinstalować pakiet nuget

image

image

image

image

 

What's New In .NET 2015

image

image

image

image

image

 

Responsive Web Design using Visual Studio

image

nowy element <picture> wprowadzany przez W3C, kompatybilność ze starszymi przeglądarkami, które tego nie zrozumieją (zinterpretują tylko img)

image

rozbudowana obsługa media queries

w Visual Studio snippety np. dla desktop, iphone itp.

image

 

ASP.NET Tooling in Visual Studio 2015

image

image

 

What's New in Visual Basic 14

image

 

image

image

image

image

image

 

Building Apps for Office Using Visual Studio

Są plany, by wtyczki w HTML5/JS/CSS były także wspierane w mobilnych aplikacjach Office

image

 

Building Cross-Platform Apps That Integrate With O365 API’s, Using Visual Studio And Cordova or Xamarin

image

image

image

image

image

image

image

 

Entity Framework 7

image

Core - funkcjonalności wspólne dla relacyjnych i nierelacyjnych źródeł danych

Rozszerzenia - funkcjonalności typowe dla danego typu źródła danych (np. klucze obce do bazy relacyjnej)

image

image

image

image

Package Manager Console:  Add-Migration InitialSchema

image

image

 

Introducing F# For The Enterprise

image

image

 

Developing Native iOS, Android, And Windows Apps In C# With Xamarin And Visual Studio 2015

image

image

image

image

image

 

.NET Native

image

image

image

Na obecny moment tylko dla aplikacji Windows Store i Windows Phone

 

Blend for Visual Studio 2015

image

image

image

image

image

image

image

 

Visual Studio: An IDE For All Your Modern Devices & Services

Udoskonalenia w IDE mało przykuły moją uwagę.

 

What's New In C# 6.0

image

image

image

image

image

image

image

image

image

image

image

image

image

 

ASP.NET 5 for .NET Framework & .NET Core

image

image