-
Notifications
You must be signed in to change notification settings - Fork 0
Sumarios
fmcarvalho edited this page Oct 23, 2019
·
34 revisions
Aulas:
- 09-09-2019 - Aula 01 - Apresentação
- 11-09-2019 - Aula 02 - Kotlin
- 16-09-2019 - Aula 03 e 04 - Kotlin - laboratório
- 23-09-2019 - Aula 05 - Android Intro
- 23-09-2019 - Aula 06 - Android LifeCycle
- 30-09-2019 - Aula 07 - Eventos e Listeners
- 30-09-2019 - Aula 08 - Custom Views
-
02-10-2019 - Aula 09 -
onSaveInstanceState
eSerializable
eParcelable
-
07-10-2019 - Aula 10 -
Parcelable
-
07-10-2019 - Aula 11 -
ViewModel
-
07-10-2019 - Aula 12 -
RecyclerView
,ViewHolder
eAdapter
- 14-10-2019 - Aula 13 e 14 - Laboratorio
- 16-10-2019 - Aula 15 - Android HTTP
- 21-10-2019 - Aula 16 e 17 - Laboratorio
-
23-10-2019 - Aula 18 -
ViewModelProvider.Factory
eApplication
09-09-2019
- Apresentação.
- Âmbito da disciplina.
- Avaliação teórica e prática (3 entregas).
- Introdução ao ambiente de programação em Kotlin
- Compilador Kotlin de linha de comando (
kotlinc
) - Modelo de execução sobre a JVM
- Exercícios: Kotlin Koans
- Caracterização geral da linguagem Kotlin:
- Tipificação estática com inferência de tipos
- Object-Oriented com suporte para os estilos imperativo e funcional
- Funções:
fun [<parametros de tipo>] <nome> ([parametros formais]) : [tipo retorno] {...}
- Tipo Função -- notação especial correspondente à assinatura, i.e.
(Tipo de Parametros)
->
Tipo Retorno
- Tipo Função e.g.
(Int) -> String
,() -> Unit
, entre outros. -
Typealias e.g.
Predicate<T> = (T) -> Boolean
-
lambdas:
{ param1, param2, ... -> block }
or{ block }
-
it
-- implicit lambda parameter -
Function references -
::
like Java - SAM (Single Abstract Method) compatível com lambda
-
read-only (e.g.
listOf()
,setOf
)<vs>
mutable collections (e.g.mutableListOf
,mutableSetOf
)
-
?
for Nullable --val variable: Type? = value
-
?.
-- safe call -- access member only if notnull
. Otherwise returns null.
- Resolução do TPC 2
- Basic parts: Manifest, Main Activity e Gradle build;
-
Activity
: UI Component (subclasse deContext
) -
Activity
:- visual + comportamento
- visual (
src/main/res/layout/...xml
) + comportamento (src/main/java
) - Analogia ao front-end Web: visual (HTML e CSS) + comportamento (Javascript)
-
Activity
-- ciclo de vida, i.e.Created
,Started
(visível),Resumed
(primeiro plano),Paused
,Stopped
, etc; -
Activity
-- métodos "gancho", i.e.onCreated()
,onStarted()
, etc
-
Actvities sao iniciadas por instâncias de
Intent
-
Intent
:- mensagem assíncrona;
- ligação entre componentes (e.g. Activities)
-
Main Activity
<--
intent.action.MAIN
- UI = Layouts + Widgets:
-
Layouts =
ViewGroup
objects = widget containers -
Widgets =
View objects
= UI components e.g. botões, caixas de texto, etc
-
Layouts =
ConstraintLayout
-
Android Studio Layout Editor
--->
activity_...xml
-
R
- classe gerada dinamicamente com constantes dos identificadores (e.g.R.id.buttonSend
)
- Eventos e Listeners --
view.setOnClickListener(View -> Unit)
findViewById(@IdRes int id)
-
Intent
- representa uma mensagem assíncrona; ligação entre componentes (e.g. Activities)- e.g.
Intent(this, DisplayMessageActivity::class.java)
: -
Exlicit: identifica o tipo da actividade a ser instanciada (
DisplayMessageActivity::class.java
) -
putExtra(key, value)
egetStringExtra(key)
- e.g.
startActivity(intent)
-
Android Manifest:
android:parentActivityName
-->
navegação -
Activity
: ciclo de vida -
demo: logging lifecycle state transitions e.g.
override fun onStart(){...}
- Intercalação entre estados de activities da mesma App.
-
Lifecycle-Aware Components :
-
LifecycleOwner
---->
LifecycleObserver
myLifecycleOwner.getLifecycle().addObserver(MyObserver())
- e.g.
@OnLifecycleEvent(Lifecycle.Event.ON_START)
-
-
Custom Views:
constructor(context: Context, attrs: AttributeSet)
-
custom drawing:
onDraw(canvas: Canvas)
ePaint
-
interaction:
override fun onTouchEvent(event: MotionEvent)
- Concepção da app
Sketcher
:-
SketcherView
--->*
Line
--->*
XyPair
-
- Implementação de
SketcherView
:
val lines : MutableList<Line> = mutableListOf()
var curr : Line? = null
override fun onDraw(canvas: Canvas) = lines.forEach { it.draw(canvas) }
override fun onTouchEvent(event: MotionEvent): Boolean { ... }
- TPC: Identificar a instrução em falta para que a UI seja actualizada em resposta da interacção com utilizador.
-
Activity
--onSaveInstanceState(Bundle)
eonRestoreInstanceState(Bundle)
-
Bundle
:- Pares chave--valor
-
put<Primitive>
ouput<Primitive>Array
- Instâncias de tipos complexos
=>
Serializable
!!! Atenção aos custos !!!- Alternativa
Parcelable
- Alternativa
- Implementar
Serializable
emLine
eXyPair
-
View
--onSaveInstanceState(): Parcelable
eonRestoreInstanceState(state: Parcelable)
- Implementar
Parcelable
emLine
eXyPair
:writeToParcel(dest: Parcel) : T
-
Parcelable.Creator<T>
::
createFromParcel(source: Parcel) : T
-
Parcelable.Creator<T>
::
newArray(int size) : Array<T>
-
TPC: Completar a implementação de
Parcelable
emLine
. SubstituirSerializable
porParcelable
emon<Save|Restores>InstanceState
- Implementação de
Parcelable
- Evitar a criação de um array intermédio.
- Teste unitário para a implementação de
Parcelable
- !!! Problema: obter uma instância real de
Parcel
? (depende da infra-estrutura Android) - Robolectric framework -- ambiente Android para os testes unitários.
androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0
- Adicionar
ViewModel
a sketcher app:class SketcherModel : ViewModel()
- Mover
lines
paraSketcherViewModel
- Transformação do desenho da aplicação
Sketcher
paraViewModel
:-
MainActivity
--->1
SketcherView
---->*
Line
---->*
XyPair
-
MainActivity
--->1
SketcherView
--->1
SketcherViewModel
---->*
Line
---->*
XyPair
-
-
SketcherView
--->1
SketcherViewModel
através de:ViewModelProviders.of(ctx)[SketcherModel::class.java]
- Instância de
ViewModel
é gerida pela infra-estrutura.
-
RecyclerView
-- 1. scrolling list, 2. large data sets, 3. data that frequently changes - Dependência gradle:
'androidx.recyclerview:recyclerview:1.0.0'
-
RecyclerView
:-
view holder object:
- Um objecto por cada elemento visualizado
- Instância de
RecyclerView.ViewHolder
- São instanciados apenas o número de view holders necessários à UI
-
view holder objects -- geridos por adapters -- instâncias de
RecyclerView.Adapter
. -
adapter -- liga (binds) view holders aos seus dados
--->
onBindViewHolder()
-
view holder object:
- Imlementação de
RecyclerView.Adapter
:class <Name> : RecyclerView.Adapter<ViewHolder_Name>()
-
override fun getItemCount()
-- número de elementos na fonte de dados -
override fun onBindViewHolder(holder ...)
-- atribui dados aoholder
-
override fun onCreateViewHolder(parent ... )
:- Obtém a
View
correspondente a um layout -
Inflate parent com a
View
do ponto 1. - Instancia e retorna um novo
ViewHolder
- Obtém a
- Implementação da App GeniuZ para apresentação de informações da Last.fm Web API.
- Utilização de
RecyclerView
com implementação deArtistAdapter
para dados só em memória (i.e.Array<ArtistDto>
) -
LayoutManager
eLinearLayoutManager
- Android HTTP framework envolve várias acções:
- Construção de um pedido HTTP
- Execução
- Obtenção da resposta
-
Parsing headers e body e.g. JSON
=>
Objecto - Actualizar a UI.
- Problema: operações de IO, parsing ou qq trabalho de background não pode ocupar a UI thread
- App Resources
- Tipos de recursos por pasta, e.g.
layout
,values
, etc. - Recursos alternativos
res/<resource_name>-<qualifier>
e.g.res/values-pt/strings.xml
- App GeniuZ simulação de obtenção dos dados sobre
LastfmWebApiMock
RecyclerView.Adapter::notifyDataSetChanged()
- Introduzir
ViewModel
para manutenção de estado em reconfiguração
- Problema: operações de IO, parsing ou qq trabalho de background não pode ocupar a UI thread
- Observar o resultado de executar IO na main thread:
- Exemplo: pedido HTTP bloqueante via
URL
(LastfmWebApiBlocking
) - NetworkOnMainThreadException
- Exemplo: pedido HTTP bloqueante via
- Distinção entre idioma Sync versus Async:
-
Sync: Resultado
=
Retorno do método=>
Conclusão da execução do método -
Async: Resultado
!=
Retorno do método
-
Sync: Resultado
'com.android.volley:volley:1.1.1'
-
Volley - biblioteca HTPT para Android:
-
RequestQueue
---->*
Request
- Gestão de worker threads
- Entrega a resposta de volta à main thread (
=>
actualização safe da UI)
-
Volley.newRequestQueue(context)
queue.add(request)
StringRequest(Request.Method,<url>,Response.Listener<String>,Response.ErrorListener)
-
AndroidManifest.xml
:<uses-permission android:name="android.permission.INTERNET" />
- Implementação de
LastfmWebApi
via Volley com API baseada em callbacks
- !!!! Problema: Reconfiguração gera novo pedido HTTP na
AlbumsActivity
-
Refactoring: mover a propriedade
LastfmWebApi
daActivity
para oViewModel
-
Activity
1 -----> 1
ViewModel
-
Activity
-->
ViewModel
-->
LastfmWebApi
-
=>
ArtistsViewModel
passa a ser instanciado por umViewModelProvider.Factory
- e.g.
LasftfmViewModelProviderFactory
- e.g.
-
Application
-- Classe base para manter o estado global da aplicação.- e.g
GeniuzApp
-- para manter uma instância deLastfmWebApi
- Manifesto:
<application android:name=".GeniuzApp"
... />`
- e.g
ViewModelProviders.of(this, LasftfmViewModelProviderFactory(application as GeniuzApp))
- !!!!! Problema: Processamento demorado do pedido HTTP na UI Thread impede a sua actualização (e.g. reconfiguração)
-
Asynchronous Task
=
- Computation that runs on a background thread
+
- Result published on the UI thread.
-
AsyncTask<Params, Progress, Result>
:doInBackground(args: vararg Params) : Result
onProgressUpdate(progress: Progress)
onPostExecute(result: Result)
- E.g.
MyAsyncTask().execute(arg1, arg2)
- Pedido HTTP com parsing JSON em background numa
AsyncTask
- E.g.
AsyncTask<String, Int, SearchDto>()
:doInBackground(vararg resp: String): SearchDto
onPostExecute(result: SearchDto) = onSuccess(result)