Loading presentation...

Present Remotely

Send the link below via email or IM

Copy

Present to your audience

Start remote presentation

  • Invited audience members will follow you as you navigate and present
  • People invited to a presentation do not need a Prezi account
  • This link expires 10 minutes after you close the presentation
  • A maximum of 30 users can follow your presentation
  • Learn more about this feature in our knowledge base article

Do you really want to delete this prezi?

Neither you, nor the coeditors you shared it with will be able to recover it again.

DeleteCancel

Make your likes visible on Facebook?

Connect your Facebook account to Prezi and let your likes appear on your timeline.
You can change this under Settings & Account at any time.

No, thanks

GDG Firenze - AndroidAnnotations

No description
by

Fabio Collini

on 18 March 2013

Comments (0)

Please log in to add your comment.

Report abuse

Transcript of GDG Firenze - AndroidAnnotations

AndroidAnnotations Fabio Collini @EActivity(R.layout.activity_main)
@OptionsMenu(R.menu.main_menu)
public class MainActivity extends Activity {

@InstanceState
ArrayList<App> apps;

@ViewById
ListView list;

@Bean
AppsLoader appsLoader;

@Bean
WelcomeMessageManager welcomeMessageManager;

@AfterViews
@Background
void initListData() {
if (apps == null) {
apps = appsLoader.loadData();
}
updateListData();
}

@UiThread
void updateListData() {
list.setAdapter(new AppAdapter(this, apps));
}

@OptionsItem(R.id.menu_about)
void showAbout() {
startActivity(SimpleTextActivity_.intent(this).text(R.string.app_name).get());
}
} Generazione di codice compile time
Per ogni classe annotata viene generato a ogni salvataggio una classe con un underscore in fondo
Non utilizza la reflection Java per evitare problemi di performance runtime La generazione delle classi avviene usando l'Annotation processing
Il progetto deve essere configurato per generare il codice a ogni salvataggio Usando EActivity una activity viene gestita da AndroidAnnotations
Nel manifest deve essere censita la classe con l'underscore in fondo (warning!)
Il parametro dell'annotation è il layout da usare nell'activity OptionsMenu permette di dichiarare il menu da usare nell'activity
I metodi da richiamare per i vari item sono definiti usando OptionsItem @Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_about:
SimpleTextActivity.showText(this,
R.string.app_name);
return true;
}
return super.onOptionsItemSelected(item);
} Per passare i parametri a una activity viene generato un builder
Nella activity da lanciare i parametri sono campi annotati con @Extra
La stessa cosa può essere fatta per i parametri dei Fragment usando l'annotation FragmentArg public class SimpleTextActivity extends Activity {
private static final String TEXT = "TEXT";

public static void showText(Context context, int text) {
Intent intent = new Intent(context, SimpleTextActivity.class);
intent.putExtra(SimpleTextActivity.TEXT, text);
context.startActivity(intent);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.simple_text_layout);
int text = getIntent().getIntExtra(TEXT, 0);
TextView textView = (TextView) findViewById(R.id.text);
textView.setText(text);
}
} Per evitare di richiamare più volte il metodo findViewById di solito le View sono salvate come campi della classe
I metodi annotati con @AfterViews sono eseguiti dopo l'injection delle view public class MainActivity extends Activity {
private ListView list;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list = (ListView) findViewById(R.id.list);
//...
}
//...
} Ogni Activity deve salvare il proprio stato perchè potrebbe essere distrutta e ricreata per esempio per un cambio di orientation public class MainActivity extends Activity {

private static final String APPS = "apps";
private ArrayList<App> apps;

@Override
protected void onCreate(Bundle state) {
super.onCreate(state);
if (state != null) {
apps = state.getParcelableArrayList(APPS);
}
}


@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelableArrayList(APPS, apps);
}
} AndroidAnnotations gestisce anche l'injection di bean
Un bean può essere definito con l'annotation @EBean
I metodi annotati con @AfterInject sono eseguiti dopo l'injection dei bean @EBean
public class AppsLoader {

@RootContext
Context context;

public ArrayList<App> loadData() {
PackageManager pm = context.getPackageManager();
Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> activities =
pm.queryIntentActivities(mainIntent, 0);
ArrayList<App> apps = new ArrayList<App>(activities.size());

for (ResolveInfo resolveInfo : activities) {
apps.add(new App(resolveInfo.loadLabel(pm).toString(), resolveInfo.activityInfo.packageName));
}
return apps;
}
} Task potenzialmente lunghi Le SharedPreferences sono usate per salvare dati primitivi non strutturati public class WelcomeMessageManager {

private static final String FIRST_TIME = "FIRST_TIME";

public static void showWelcomeMessage(Context context) {
SharedPreferences prefs =
PreferenceManager.getDefaultSharedPreferences(context);
if (prefs.getBoolean(FIRST_TIME, true)) {
SimpleTextActivity.showText(context, R.string.welcome);
prefs.edit().putBoolean(FIRST_TIME, false).commit();
}
}

} Usando AndroidAnnotations le SharedPreferences diventano typesafe Una classe ViewHolder viene usata nelle ListView per minimizzare le chiamate a findViewById public final class AppAdapter extends ArrayAdapter<App> {
public AppAdapter(Context context, List<App> objects) {
super(context, 0, objects);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
AppViewHolder holder;
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(
android.R.layout.simple_list_item_2, parent, false);
holder = new AppViewHolder(convertView);
convertView.setTag(holder);
} else {
holder = (AppViewHolder) convertView.getTag();
}
holder.bind(getItem(position));
return convertView;
}
} Fabio Collini @fabioCollini
linkedin.com/in/fabiocollini

Responsabile Area Web & mobile
Docente corsi Android
www.omniagroup.it

Android Developer
Apps Organizer e Folder Organizer

Blogger
www.cosenonjaviste.it Robert C. Martin The ratio of time spent reading [code] versus writing is well over 10 to 1 [therefore] making it easy to read makes it easier to write. Riferimenti http://androidannotations.org/
http://github.com/excilys/androidannotations Thanks for your attention! Questions?

Fabio Collini
@fabioCollini
linkedin.com/in/fabiocollini
www.omniagroup.it
www.cosenonjaviste.it Da dove iniziare Download Android Development Tools
http://developer.android.com/sdk/index.html

Generatore di progetti
http://androidkickstartr.com/ AndroidAnnotations @Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.main_menu, menu);
return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
boolean handled = super.onOptionsItemSelected(item);
if (handled) {
return true;
}
int itemId_ = item.getItemId();
if (itemId_ == id.menu_about) {
showAbout();
return true;
}
return false;
} startActivity(SimpleTextActivity_.intent(this).text(
R.string.app_name).get());

@EActivity(R.layout.simple_text_layout)
@NoTitle
public class SimpleTextActivity extends Activity {
@Extra
int text;

@ViewById(R.id.text)
TextView textView;

@AfterViews
void initText() {
textView.setText(text);
}
} Android è un sistema operativo mobile Come funziona AndroidAnnotations Thread in background Aggiornamenti della UI Thread principale L'Android sdk mette a disposizione:
AsyncTask
Loader public class AppViewHolder {

private TextView text1;
private TextView text2;

public AppViewHolder(View convertView) {
text1 = (TextView)
convertView.findViewById(android.R.id.text1);
text2 = (TextView)
convertView.findViewById(android.R.id.text2);
}

public void bind(App item) {
text1.setText(item.getName());
text2.setText(item.getPackageName());
}

} @EViewGroup(android.R.layout.simple_list_item_2)
public class AppViewHolder extends RelativeLayout {

@ViewById(android.R.id.text1)
TextView text1;

@ViewById(android.R.id.text2)
TextView text2;

public AppViewHolder(Context context) {
super(context);
}

public void bind(App item) {
text1.setText(item.getName());
text2.setText(item.getPackageName());
}

} public final class AppAdapter extends ArrayAdapter<App> {
public AppAdapter(Context context, List<App> objects) {
super(context, 0, objects);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
AppViewHolder appViewHolder;
if (convertView == null) {
appViewHolder = AppViewHolder_.build(getContext());
} else {
appViewHolder = (AppViewHolder) convertView;
}
appViewHolder.bind(getItem(position));
return appViewHolder;
}
} La reflection è lenta Creare troppi oggetti penalizza le performance Molti framework J2EE non sono usabili MVC usato poco Framework open source sviluppato da Pierre-Yves Ricau @pyricau, Mathieu Boniface @matboniface e Alexis THOMAS @ath0mas con contributi di altri developer
Mette a disposizione varie annotation per semplificare la scrittura del codice Android public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
} @SharedPref(Scope.APPLICATION_DEFAULT)
public interface FirstTimePref {
@DefaultBoolean(true)
boolean firstTime();
}

@EBean
public class WelcomeMessageManager {
@RootContext
Context context;
@Pref
FirstTimePref_ prefs;

@AfterViews
public void showWelcomeMessage() {
if (prefs.firstTime().get()) {
context.startActivity(SimpleTextActivity_
.intent(context).text(R.string.welcome).get());
prefs.edit().firstTime().put(false).apply();
}
}
} Per gli altri componenti è possibile usare @EApplication, @EService, @EReceiver, @EProvider e @EFragment E' possibile usare anche @NonConfigurationInstance per gestire gli oggetti non salvabili in un bundle Pro e contro Codice più semplice da leggere .

Si perde un po' di "aiuto del compilatore" ma abbiamo comunque warning e errori custom di AndroidAnnotations

Migliore organizzazione del codice grazie alla DI .

Le classi generate sono nel progetto, il debug non è più complicato dei progetti standard

Qualche clean di Eclipse in più da fare .
Full transcript