SlideShare a Scribd company logo
11
MVVM - IOS, ANDROID, XAMARIN
GUILHERME ENDRES
22
MVVM - IOS, ANDROID, XAMARIN
GUILHERME ENDRES
TDC2016SP - Trilha Mobile
MVVM
!= !=
MVVM IOS
IOS | MVC
Model View Controller
IOS | MVC
Model View
View
Controller
Massive View Controller
IOS | MVC
TDC2016SP - Trilha Mobile
TDC2016SP - Trilha Mobile
M V V M
Model ViewModelView
View
Controller
IOS | MVVM
TDC2016SP - Trilha Mobile
Model
Nome
Preço
Teor Alcoólico
Marca
IOS | MODEL
Model ViewModelView
View
Controller
IOS | MVVM
ViewModel
BANCO DE DADOS
VALIDAÇÃO DE DADOS
MANIPULAÇÃO DE MODELOS
IOS | VIEW MODEL
Model ViewModelView
View
Controller
IOS | MVVM
ViewModel
View
Controller
4.5%
R$ 5,00
TDCBeer
Pale Ale
Model
swift
var beerView = BeerView( beerViewModel )
var beerView = BeerView( beerViewModel )
var beerViewController = BeerViewController()
beerViewController.beerView = beerView
var beerViewController = BeerViewController( beerViewModel)
Model ViewModelView
View
Controller
IOS | MVVM
ViewModel
View
Controller
beerViewModel.quantity = 5
imageView.image = beerViewModel.image
beerViewModel.quantity = textField.text
beerViewModel.image { image in
imageView.image = image
}
IOS | COMUNICAÇÃO
DELEGATE
KVO
BINDING
THIRD PARTY
beerViewModel.addObserver(self,
forKeyPath: "userImage",
options: .New,
context: &imageContext)
BINDING | KVO
beerViewModel.addObserver(self,
forKeyPath: "userImage",
options: .New,
context: &imageContext)
deinit {
beerViewModel.removeObserver(self, forKeyPath: "userImage")
}
BINDING | KVO
override func observeValueForKeyPath(keyPath: String,
ofObject object: AnyObject,
change: [NSObject: AnyObject],
context: UnsafeMutablePointer<Void>) {
if context == &imageContext {
self.imageView.image= change[NSKeyValueChangeNewKey]
}
}
BINDING | KVO
override func observeValueForKeyPath(keyPath: String,
ofObject object: AnyObject,
change: [NSObject: AnyObject],
context: UnsafeMutablePointer<Void>) {
if context == &imageContext {
self.imageView.image= change[NSKeyValueChangeNewKey]
} else if context == &quantityContext {
self.textField.text = change[NSKeyValueChangeNewKey]
}
}
BINDING | KVO
override func observeValueForKeyPath(keyPath: String,
ofObject object: AnyObject,
change: [NSObject: AnyObject],
context: UnsafeMutablePointer<Void>) {
if context == &imageContext {
self.imageView.image= change[NSKeyValueChangeNewKey]
} else if context == &quantityContext {
self.textField.text = change[NSKeyValueChangeNewKey]
}
}
BINDING | KVO
else if context == &context {
self.variable = change[NSKeyValueChangeNewKey]
}else if context == &context {
self.variable = change[NSKeyValueChangeNewKey]
}
else if context == &context {
self.variable = change[NSKeyValueChangeNewKey]
}
else if context == &context {
self.variable = change[NSKeyValueChangeNewKey]
else if context == &context {
self.variable = change[NSKeyValueChangeNewKey]
}
else if context == &context {
self.variable = change[NSKeyValueChangeNewKey
}
else if context == &context {
self.variable = change[NSKeyValueChangeNewKey
}
else if context == &context {
self.variable = change[NSKeyValueChangeNewKey]
}
else if context == &context {
self.variable = change[NSKeyValueChangeNewKey]
}
else if context == &context {
self.variable = change[NSKeyValueChangeNewKey]
}
TDC2016SP - Trilha Mobile
DELEGATE
KVO
BINDING
THIRD PARTY
protocol BeerViewModelDelegate {
func viewModelDidUpdate()
}
BINDING | DELEGATE
protocol BeerViewModelDelegate {
func viewModelDidUpdate()
}
class BeerViewModel {
var delegate: BeerViewModelDelegate?
//Quando atualizar
delegate!.viewModelDidUpdate()
}
BINDING | DELEGATE
class ViewController {
beerViewModel.delegate = self
func viewModelDidUpdate() {
imageView.image = beerViewModel.userImage
}
}
BINDING | DELEGATE
DELEGATE
KVO
BINDING
THIRD PARTY
Swift
ReactiveCocoa4
BINDING | THIRD PARTY
TDC2016SP - Trilha Mobile
<~<~
errorLabel.rac_text <~ userViewModel.errorMessage
errorLabel.rac_hidden <~ userViewModel.usernameCorrect
UserViewController
errorLabel.rac_text <~ userViewModel.errorMessage
errorLabel.rac_hidden <~ userViewModel.usernameCorrect
enterButton.rac_hidden <~ userViewModel.hiddenButton
UserViewController
imageView.image <~ beerViewModel
.userImage
BeerViewController
UNIT TEST
let userViewModel: UserViewModel = UserViewModel()
IOS | UNIT TEST
let userViewModel: UserViewModel = UserViewModel()
userViewModel.username.value = "Skywalker"
IOS | UNIT TEST
let userViewModel: UserViewModel = UserViewModel()
userViewModel.username.value = "Skywalker"
userViewModel.saveUser().on(
completed: {
// success
}, failed: { error in
// fail
}).start()
IOS | UNIT TEST
userViewModel.saveUser().on(
completed: {
// success
}, failed: { error in
// fail
}).start()
IOS | UNIT TEST
userViewModel.username.value = "Darth Vader"
userViewModel.saveUser().on(
completed: {
// fail
}, failed: { error in
// success
}).start()
IOS | UNIT TEST
TDC2016SP - Trilha Mobile
MVVM ANDROID
MVVM?
MVVM Data Binding!
MVVM Data Binding!
Android?
MVVM Data Binding!
Android?
SIM!
ANDROID DATA BINDING LIBRARY
ATIVANDO DATA BINDING
android {

....

dataBinding {

enabled = true

}

}
ANTES…
<EditText

android:id="@+id/beer_count_edit_text"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:gravity="end"

android:inputType="numberDecimal"

android:singleLine="true" />
EditText beerCountEditText = (EditText)findViewById(R.id.beer_count_edit_text);

beerCountEditText.setText(beerViewModel.getBeerCount());
USANDO DATA BINDING LIBRARY
<data>

<variable

name="beerViewModel"

type="com.arctouch.beerbind.beer.BeerCountViewModel" />

</data>
<EditText

android:id="@+id/beer_count_edit_text"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:gravity="end"

android:inputType="numberDecimal"

android:singleLine="true" />
USANDO DATA BINDING LIBRARY
<EditText

android:id="@+id/beer_count_edit_text"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:gravity="end"

android:inputType="numberDecimal"

android:singleLine="true"
android:text="@{beerViewModel.beerCountText}" />
<data>

<variable

name="beerViewModel"

type="com.arctouch.beerbind.beer.BeerCountViewModel" />

</data>
TWO-WAY BINDING
<EditText

android:id="@+id/beer_count_edit_text"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:gravity="end"

android:inputType="numberDecimal"

android:singleLine="true"
android:text="@{beerViewModel.beerCountText}" />
<data>

<variable

name="beerViewModel"

type="com.arctouch.beerbind.beer.BeerCountViewModel" />

</data>
TWO-WAY BINDING
<EditText

android:id="@+id/beer_count_edit_text"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:gravity="end"

android:inputType="numberDecimal"

android:singleLine="true"
android:text="@{beerViewModel.beerCountText}"
app:addTextChangedListener="@{beerViewModel.beerCountTextWatcher}" />
<data>

<variable

name="beerViewModel"

type="com.arctouch.beerbind.beer.BeerCountViewModel" />

</data>
TWO-WAY BINDING
<EditText

android:id="@+id/beer_count_edit_text"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:gravity="end"

android:inputType="numberDecimal"

android:singleLine="true"
android:text="@{beerViewModel.beerCountText}"
app:addTextChangedListener="@{beerViewModel.beerCountTextWatcher}" />
public TextWatcher getBeerCountTextWatcher() {

return new TextWatcher() { 

@Override

public void afterTextChanged(Editable s) {

setBeerCount(Integer.parseInt(s.toString()));

}

};

}
ACTIVITY
@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

ActivityBeerBinding binding = 

DataBindingUtil.setContentView(this, R.layout.activity_beer);


BeerCountViewModel beerViewModel = 

new BeerCountViewModel(new BeerCountModel());

binding.setBeerViewModel(beerViewModel);

}
ACTIVITY
@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

ActivityBeerBinding binding = 

DataBindingUtil.setContentView(this, R.layout.activity_beer);


BeerCountViewModel beerViewModel = 

new BeerCountViewModel(new BeerCountModel());

binding.setBeerViewModel(beerViewModel);

}
FRAGMENT
@Override

public View onCreateView(…){


ActivityBeerBinding binding =

DataBindingUtil.inflate(inflater, R.layout.activity_beer,
container, false);


BeerCountViewModel viewModel =

new BeerCountViewModel(new BeerCountModel());


binding.setBeerViewModel(viewModel);

return binding.getRoot();

}
FRAGMENT
@Override

public View onCreateView(…){


ActivityBeerBinding binding =

DataBindingUtil.inflate(inflater, R.layout.activity_beer,
container, false);


BeerCountViewModel viewModel =

new BeerCountViewModel(new BeerCountModel());


binding.setBeerViewModel(viewModel);

return binding.getRoot();

}
VIEW MODEL
public class BeerCountViewModel extends BaseObservable {



private int beerCount;



@Bindable

public int getBeerCount() {

return beerCount;

}



public void setBeerCount(int beerCount) {

this.beerCountModel.setBeerCount(beerCount);

notifyPropertyChanged(BR.beerCount);

}



}
VIEW MODEL
extends BaseObservable {

t beerCount) {

BeerCount(beerCount);

R.beerCount);

• Classe base
• Implementa a interface
Observable
• Usado pra notificar a
mudanças para a view
VIEW MODEL
public class BeerCountViewModel extends BaseObservable {



private int beerCount;



@Bindable

public int getBeerCount() {

return beerCount;

}



public void setBeerCount(int beerCount) {

this.beerCountModel.setBeerCount(beerCount);

notifyPropertyChanged(BR.beerCount);

}



}
VIEW MODEL
ublic class BeerCountViewModel extends BaseObservable {

private int beerCount;

@Bindable

public int getBeerCount() {

return beerCount;

}

public void setBeerCount(int beerCount) {

this.beerCountModel.setBeerCount(beerCount);

notifyPropertyChanged(BR.beerCount);

}

VIEW MODEL
ublic class BeerCountViewModel extends BaseObservable {

private int beerCount;

@Bindable

public int getBeerCount() {

return beerCount;

}

public void setBeerCount(int beerCount) {

this.beerCountModel.setBeerCount(beerCount);

notifyPropertyChanged(BR.beerCount);

}

CUSTOM SETTER
@BindingAdapter("app:imageUrl")

public static void loadImage(ImageView imageView, String url) {

Glide.with(imageView.getContext())

.load(url)

.into(imageView);
}
<ImageView

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layout_marginTop="@dimen/default_margin"

app:imageUrl="@{beerViewModel.imageUrl}" />
ANDROID DATA BINDING
• One-way binding:
• Two-way binding:
• Custom setters:
ANDROID DATA BINDING
• One-way binding:
• Two-way binding:
• Custom setters:
ANDROID DATA BINDING
• One-way binding:
• Two-way binding:
• Custom setters:
ANDROID DATA BINDING
• One-way binding:
• Two-way binding:
• Custom setters:
MVVM XAMARIN
No .NET desde 2008
TDC2016SP - Trilha Mobile
XAMARIN | MVVM
VIEW (XAML)
VIEWMODEL
MODEL
Command BindingContext / Binding
Read/Update
INotifyPropertyChanged
BindableObject
using System;



namespace System.ComponentModel

{

public interface INotifyPropertyChanged

{

//

// Events

//

event PropertyChangedEventHandler PropertyChanged;

}

}
XAMARIN | Data Binding
XAMARIN | Data Binding
public abstract class BaseViewModel : INotifyPropertyChanged

{

public event PropertyChangedEventHandler PropertyChanged;



protected void OnPropertyChanged([CallerMemberName] string propertyName = null)

{

PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

}

}

XAMARIN | Data Binding
private string errorMessage;

public string ErrorMessage

{

get { return this.errorMessage; }

set

{

this.errorMessage = value;

OnPropertyChanged();

}

}
XAMARIN | Data Binding - Genérico
protected bool SetPropertyAndNotify<T>(ref T storage, T value,
[CallerMemberName] string propertyName = null)

{

if (Equals(storage, value))

{

return false;

}



storage = value;

OnPropertyChanged(propertyName);

return true;

}

this.myField = value;
XAMARIN | Data Binding
private string errorMessage;

public string ErrorMessage

{

get { return this.errorMessage; }

set

{

this.errorMessage = value;

OnPropertyChanged();

}

}
XAMARIN | Data Binding
private string errorMessage;

public string ErrorMessage

{

get { return this.errorMessage; }

set { SetPropertyAndNotify(ref this.errorMessage, value); }

}

XAMARIN | Data Binding
<Label

Text="{Binding ErrorMessage}"

TextColor="White"

FontSize="17"

HorizontalTextAlignment="Center"

FontFamily="HelveticaNeue-CondensedBold"

HorizontalOptions="Center"

HeightRequest="20"/>
<ContentPage.BindingContext>

<custom:UserViewModel />

</ContentPage.BindingContext>
UserView.xaml
<StackLayout>
<Label Text="{Binding ErrorMessage}” />

<Entry Placeholder="Digite seu nome aqui"

Text="{Binding Username}"/>

<Button Text="ENTER"

Command="{Binding EnterCommand}”
IsVisible="{Binding IsUsernameValid}”/>
</StackLayout>
UserView.xaml
public class UserViewModel : BaseViewModel

public string Username

{

get { return this.username; }

set

{

SetPropertyAndNotify(ref this.username, value);

ValidateUsername();

}

}
UserViewModel
Apenas validação simples!



Sem longos processamentos e/ou
chamadas assíncronas.

Ex:. APIs ou banco de dados
<Slider Maximum=“20" Minimum="0"

Value="{Binding DrankBeersCount, Mode=TwoWay}"/>

BeerView.xaml
public int DrankBeersCount

{

get

{

return this.drankBeersCount;

}

set

{

SetPropertyAndNotify(ref this.drankBeersCount, value);

OnPropertyChanged(nameof(DrunkenPersonImage));

}

}



public string DrunkenPersonImage

{

get { return GetBeerImage(DrankBeersCount); }

}

BeerViewModel
COMPARAÇÃO MVVM
IOS/ANDROID/XAMARIN
Suporte MVVM | Comparação entre plataformas
Anunciado em 2015/Android M +
No .NET desde 2008
Delegate / KVO / ReactiveCocoa
iOS: https://github.com/gfendres/ractdc2016
Android: https://github.com/thiagocechetto/BeerBind
Xamarin: https://github.com/oberdanf/tdc2016mvvm
OBRIGADO.
Big Brains Wanted
Join our team! Go to arctouch.com/brjobs
guilherme.endres@arctouch.com

More Related Content

PPTX
[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache Cordova
PPTX
[JavaLand 2015] Developing JavaScript Mobile Apps Using Apache Cordova
PPTX
Apache Cordova In Action
PPTX
[Devoxx Morocco 2015] Apache Cordova In Action
PDF
190 959
PDF
Ionic으로 모바일앱 만들기 #3
PPTX
ATAGTR2017 Upgrading a mobile tester's weapons with advanced debugging
PDF
jsf2 Notes
[JMaghreb 2014] Developing JavaScript Mobile Apps Using Apache Cordova
[JavaLand 2015] Developing JavaScript Mobile Apps Using Apache Cordova
Apache Cordova In Action
[Devoxx Morocco 2015] Apache Cordova In Action
190 959
Ionic으로 모바일앱 만들기 #3
ATAGTR2017 Upgrading a mobile tester's weapons with advanced debugging
jsf2 Notes

Viewers also liked (20)

PPT
TDC2016SP - Trilha Mobile
PPTX
Xamarin Hack Day - Sydney 2016 - Introduction to Xamarin
PPTX
JXUGC #9 Xamarin.Forms Mvvm Teachathon
PPTX
Training: MVVM Pattern
PPTX
Mobile development strategies with MVVM
PDF
TDC2016SP - Trilha Impressão 3D
PDF
TDC2016SP - Trilha Impressão 3D
PPTX
TDC2016SP - Trilha NoSQL
PPT
TDC2016SP - Trilha NoSQL
PPT
TDC2016SP - Trilha NoSQL
PPTX
TDC2016SP - Trilha NoSQL
PDF
TDC2016SP - Trilha Startups
PDF
TDC2016SP - Trilha NoSQL
PDF
Tomada de Decisão baseada em testes de carga - The Developer`s Conference Sã...
PPTX
TDC2016SP - Trilha NoSQL
PPT
TDC2016SP - Trilha Startups
PPTX
Testando sua aplicação asp.net mvc de forma automatizada de ponta a ponta
PPT
TDC2016SP - Trilha Node.Js
PDF
TDC2016SP - Trilha Arquitetura Empresarial
TDC2016SP - Trilha Mobile
Xamarin Hack Day - Sydney 2016 - Introduction to Xamarin
JXUGC #9 Xamarin.Forms Mvvm Teachathon
Training: MVVM Pattern
Mobile development strategies with MVVM
TDC2016SP - Trilha Impressão 3D
TDC2016SP - Trilha Impressão 3D
TDC2016SP - Trilha NoSQL
TDC2016SP - Trilha NoSQL
TDC2016SP - Trilha NoSQL
TDC2016SP - Trilha NoSQL
TDC2016SP - Trilha Startups
TDC2016SP - Trilha NoSQL
Tomada de Decisão baseada em testes de carga - The Developer`s Conference Sã...
TDC2016SP - Trilha NoSQL
TDC2016SP - Trilha Startups
Testando sua aplicação asp.net mvc de forma automatizada de ponta a ponta
TDC2016SP - Trilha Node.Js
TDC2016SP - Trilha Arquitetura Empresarial
Ad

Similar to TDC2016SP - Trilha Mobile (20)

PDF
The Rails Way
PPTX
Valentine with AngularJS
PDF
Component Based UI Architecture - Alex Moldovan
PDF
JavaCro'14 - Vaadin web application integration for Enterprise systems – Pete...
PDF
Building Mobile Friendly APIs in Rails
PDF
Dialogs in Android MVVM (14.11.2019)
PPTX
MVVM Lights
PDF
Intro Angular Ionic
PDF
Backbone.js with React Views - Server Rendering, Virtual DOM, and More!
PDF
MVVM-C vs MVP
PPT
CTTDNUG ASP.NET MVC
PPTX
AngularJS in 60ish Minutes
PDF
From mvc to viper
PDF
7 Ways to improve your gradle build
PDF
[22]Efficient and Testable MVVM pattern
PDF
Use case driven architecture
PPTX
Mvvm + behaviors
PPTX
Controllers & actions
PPTX
Web deploy
PDF
Vue.js part1
The Rails Way
Valentine with AngularJS
Component Based UI Architecture - Alex Moldovan
JavaCro'14 - Vaadin web application integration for Enterprise systems – Pete...
Building Mobile Friendly APIs in Rails
Dialogs in Android MVVM (14.11.2019)
MVVM Lights
Intro Angular Ionic
Backbone.js with React Views - Server Rendering, Virtual DOM, and More!
MVVM-C vs MVP
CTTDNUG ASP.NET MVC
AngularJS in 60ish Minutes
From mvc to viper
7 Ways to improve your gradle build
[22]Efficient and Testable MVVM pattern
Use case driven architecture
Mvvm + behaviors
Controllers & actions
Web deploy
Vue.js part1
Ad

More from tdc-globalcode (20)

PDF
TDC2019 Intel Software Day - Visao Computacional e IA a servico da humanidade
PDF
TDC2019 Intel Software Day - Tecnicas de Programacao Paralela em Machine Lear...
PDF
TDC2019 Intel Software Day - ACATE - Cases de Sucesso
PDF
TDC2019 Intel Software Day - Otimizacao grafica com o Intel GPA
PDF
TDC2019 Intel Software Day - Deteccao de objetos em tempo real com OpenVino
PDF
TDC2019 Intel Software Day - OpenCV: Inteligencia artificial e Visao Computac...
PDF
TDC2019 Intel Software Day - Inferencia de IA em edge devices
PDF
Trilha BigData - Banco de Dados Orientado a Grafos na Seguranca Publica
PPT
Trilha .Net - Programacao funcional usando f#
PDF
TDC2018SP | Trilha Go - Case Easylocus
PDF
TDC2018SP | Trilha Modern Web - Para onde caminha a Web?
PDF
TDC2018SP | Trilha Go - Clean architecture em Golang
PDF
TDC2018SP | Trilha Go - "Go" tambem e linguagem de QA
PDF
TDC2018SP | Trilha Mobile - Digital Wallets - Seguranca, inovacao e tendencia
PDF
TDC2018SP | Trilha .Net - Real Time apps com Azure SignalR Service
PDF
TDC2018SP | Trilha .Net - Passado, Presente e Futuro do .NET
PDF
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
PDF
TDC2018SP | Trilha .Net - Obtendo metricas com TDD utilizando build automatiz...
PDF
TDC2018SP | Trilha .Net - .NET funcional com F#
PDF
TDC2018SP | Trilha .Net - Crie SPAs com Razor e C# usando Blazor em .Net Core
TDC2019 Intel Software Day - Visao Computacional e IA a servico da humanidade
TDC2019 Intel Software Day - Tecnicas de Programacao Paralela em Machine Lear...
TDC2019 Intel Software Day - ACATE - Cases de Sucesso
TDC2019 Intel Software Day - Otimizacao grafica com o Intel GPA
TDC2019 Intel Software Day - Deteccao de objetos em tempo real com OpenVino
TDC2019 Intel Software Day - OpenCV: Inteligencia artificial e Visao Computac...
TDC2019 Intel Software Day - Inferencia de IA em edge devices
Trilha BigData - Banco de Dados Orientado a Grafos na Seguranca Publica
Trilha .Net - Programacao funcional usando f#
TDC2018SP | Trilha Go - Case Easylocus
TDC2018SP | Trilha Modern Web - Para onde caminha a Web?
TDC2018SP | Trilha Go - Clean architecture em Golang
TDC2018SP | Trilha Go - "Go" tambem e linguagem de QA
TDC2018SP | Trilha Mobile - Digital Wallets - Seguranca, inovacao e tendencia
TDC2018SP | Trilha .Net - Real Time apps com Azure SignalR Service
TDC2018SP | Trilha .Net - Passado, Presente e Futuro do .NET
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
TDC2018SP | Trilha .Net - Obtendo metricas com TDD utilizando build automatiz...
TDC2018SP | Trilha .Net - .NET funcional com F#
TDC2018SP | Trilha .Net - Crie SPAs com Razor e C# usando Blazor em .Net Core

Recently uploaded (20)

PDF
Empowerment Technology for Senior High School Guide
PPTX
Virtual and Augmented Reality in Current Scenario
PPTX
CHAPTER IV. MAN AND BIOSPHERE AND ITS TOTALITY.pptx
PPTX
A powerpoint presentation on the Revised K-10 Science Shaping Paper
PPTX
Onco Emergencies - Spinal cord compression Superior vena cava syndrome Febr...
PDF
Practical Manual AGRO-233 Principles and Practices of Natural Farming
PPTX
20th Century Theater, Methods, History.pptx
PDF
Weekly quiz Compilation Jan -July 25.pdf
PPTX
Introduction to pro and eukaryotes and differences.pptx
PDF
ChatGPT for Dummies - Pam Baker Ccesa007.pdf
PPTX
Unit 4 Computer Architecture Multicore Processor.pptx
PDF
International_Financial_Reporting_Standa.pdf
PDF
Environmental Education MCQ BD2EE - Share Source.pdf
PPTX
Computer Architecture Input Output Memory.pptx
PPTX
History, Philosophy and sociology of education (1).pptx
PDF
FOISHS ANNUAL IMPLEMENTATION PLAN 2025.pdf
PDF
David L Page_DCI Research Study Journey_how Methodology can inform one's prac...
PDF
BP 704 T. NOVEL DRUG DELIVERY SYSTEMS (UNIT 2).pdf
PDF
What if we spent less time fighting change, and more time building what’s rig...
PDF
AI-driven educational solutions for real-life interventions in the Philippine...
Empowerment Technology for Senior High School Guide
Virtual and Augmented Reality in Current Scenario
CHAPTER IV. MAN AND BIOSPHERE AND ITS TOTALITY.pptx
A powerpoint presentation on the Revised K-10 Science Shaping Paper
Onco Emergencies - Spinal cord compression Superior vena cava syndrome Febr...
Practical Manual AGRO-233 Principles and Practices of Natural Farming
20th Century Theater, Methods, History.pptx
Weekly quiz Compilation Jan -July 25.pdf
Introduction to pro and eukaryotes and differences.pptx
ChatGPT for Dummies - Pam Baker Ccesa007.pdf
Unit 4 Computer Architecture Multicore Processor.pptx
International_Financial_Reporting_Standa.pdf
Environmental Education MCQ BD2EE - Share Source.pdf
Computer Architecture Input Output Memory.pptx
History, Philosophy and sociology of education (1).pptx
FOISHS ANNUAL IMPLEMENTATION PLAN 2025.pdf
David L Page_DCI Research Study Journey_how Methodology can inform one's prac...
BP 704 T. NOVEL DRUG DELIVERY SYSTEMS (UNIT 2).pdf
What if we spent less time fighting change, and more time building what’s rig...
AI-driven educational solutions for real-life interventions in the Philippine...

TDC2016SP - Trilha Mobile