Sử dụng cache trong ASP.NET MVC với Redis Cache, Memory Cache

Khi lập trình ứng dụng chúng ta hay gặp vấn đề làm sao cho tối ưu tài nguyên của hệ thống, tăng tốc độ trải nghiệm từ phía end user. Đặc biệt là các ứng dụng web.

Cache là gì ? 
Lý thuyết: Cache là tên gọi của bộ nhớ đệm – nơi lưu trữ các dữ liệu nằm chờ các ứng dụng hay phần cứng xử lý. Mục đích của nó  để tăng tốc độ xử lý (có sẵn xài liền không cần tốn thời gian đi lùng sục tìm kéo về).

Thực tế: Cache là các dữ liệu trong phiên làm việc trước của các ứng dụng, chương trình mà hệ điều hành lưu lại nhằm giúp việc tải data trong các phiên làm việc sau được nhanh hơn.

Tip này hướng dẫn các bạn cách implement cache vào ứng dụng, sử dụng thư viện đã được wrap lại từ Memery Cache & Redis Cache

Đầu tiên tải về thư viện tại Nuget: https://www.nuget.org/packages/colorlife.tuanitpro.com/

Hoặc cài đặt trực tiếp trong Visual Studio

Tạo class Customer để test

public class Customer
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

Sử dụng Memory Cache

  private static void MemoryCache_Customer_Test()
        {
            ICacheProviderFactory cacheProvideractory = new CacheProviderFactory();
            IDataCacheProvider dataCacheProvider = cacheProvideractory.CreateFactory();
            Customer customer = new Customer
            {
                FirstName = "Tuan",
                LastName = "Le"
            };
            string cacheKey = "Memory_Cache_Customer";
            dataCacheProvider.Set(cacheKey, customer);
            Console.WriteLine("Before cache: " + customer.FirstName + " " + customer.LastName);
             
            Console.WriteLine("After Update: " + customer.FirstName + " " + customer.LastName);

            var customerInCache = dataCacheProvider.Get(cacheKey);

            Console.WriteLine("Get Customer In MemoryCache: " + customerInCache.FirstName + " " + customerInCache.LastName);
        }

Sử dụng Radis Cache
Đầu tiên tải Redis cho Windows & cài đặt tại: https://github.com/MicrosoftArchive/redis/releases

Code:

  private static void RedisCache_Customer_Test()
        {
            ICacheProviderFactory cacheProvideractory = new CacheProviderFactory(new CacheProviderOptions
            {
                SlidingExpiration = TimeSpan.FromSeconds(30),
                ConnectionString = "localhost:6379" // mặc định
            }, CacheType.Redis);
            IDataCacheProvider dataCacheProvider = cacheProvideractory.CreateFactory();
            Customer customer = new Customer
            {
                FirstName = "Tuan",
                LastName = "Le"
            };
            string cacheKey = "RedisCache_Customer";
            dataCacheProvider.Set(cacheKey, customer);
            Console.WriteLine("Before cache: " + customer.FirstName + " " + customer.LastName);
            Thread.Sleep(5000);
            customer.LastName = "Le_Updated";
            Console.WriteLine("After Update: " + customer.FirstName + " " + customer.LastName);

            var customerInCache = dataCacheProvider.Get(cacheKey);

            Console.WriteLine("Customer In RedisCache: " + customerInCache.FirstName + " " + customerInCache.LastName);
        }

Thư viện còn hỗ trợ một số chức năng nho nhỏ khác, sẽ nói trong bài viết khác. Chúc các bạn thành công 🙂

Tạo bot discord check giá coinmarketcap

Các thư viện sử dụng

https://discord.js.org

https://www.npmjs.com/package/node-fetch

Yêu cầu máy đã cài nodejs

Tạo app trên discord: https://discordapp.com/developers/docs/intro

Lấy token để sử dụng sau:

Sử dụng Visual Code để code.

Tạo file bot.js

Code:

npm install discord.js

const Discord = require('discord.js');
const client = new Discord.Client();

const commandPrefix = "!";

client.on('ready', () => {
  console.log(`Logged in as ${client.user.tag}!`);
});

client.on('message', (message)=> {
    if(!message.content.startsWith(commandPrefix)) return;
    const args = message.content.slice(commandPrefix.length).trim().split(/ +/g);
    const command = args.shift().toLowerCase();
       
    switch(command){
    	case "hello":
			hello(message);
    	break;
    	case "help":
			help(message);
    	break;
    	case "ping":
			sendText(message, "Pong");
    	break;
    	case "clear":
    		clear(message);
    	break;
    	case "cmc":
    		coinmarketcap(message);
    	break;
    	case "c":
    		chart(message, args);
    	break;
    	case "p":
    		price(message, args);
    	break;    	
    	default:
    		sendText(message, "Command not found.")
    	break;
    }
});

client.login('NDQyMDAyMTAyODAyMzE3MzMz.DdMfbw.3eV-Qk5N2TpDIDgatQb1ILeD0Hc');

Các hàm chính trong bot

function hello(message){
	message.channel.send("Hello " + message.author + "! Nice to meet you. :smiley: ");
}
function help(message){
	 let embed = new Discord.RichEmbed()            
            .setAuthor("Hello world", "http://icons.iconarchive.com/icons/froyoshark/enkel/256/Bitcoin-icon.png")
            .addField("!hello", "Sends a friendly message!")
            .addField("!help", "Sends this help embed")
            .addField("!cmc", "Coin Market Cap")
            .addField("!ping", "Ping")
            .addField("!p", "Price of coin. Ex: BTCUSDT or price BTC")
            .setTitle("Bot commands:")
            .setFooter("Here you have all bot commands you can use!")
            .setColor("AQUA");        
        message.channel.send({embed: embed});
}
function sendText(message, text){
	message.channel.send(text).then(msg=>{msg.delete(10000)}); 
    message.delete(12000);
}

function clear(message){
	if (message.member.hasPermission("MANAGE_MESSAGES")) {
        message.channel.fetchMessages()
           .then(function(list){
                message.channel.bulkDelete(list);
            }, function(err){message.channel.send("ERROR: ERROR CLEARING CHANNEL.")})                        
    }
    else{
    	console.log("You don't have permission");
    }

Hàm lấy giá trên coinmarketcap.com

npm install node-fetch

function coinmarketcap(message){
	    let url = 'https://api.coinmarketcap.com/v2/global/';	
		let bitcoin_percentage_of_market_cap='';
		let total_market_cap= '';
		let total_volume_24h = '';
		let last_updated = '';
		fetch(url)
    	.then(res => res.json())
    	.then(json => {
    		// console.log(json);
    		bitcoin_percentage_of_market_cap =  json.data.bitcoin_percentage_of_market_cap;
    		total_market_cap = json.data.quotes.USD.total_market_cap;
 			total_volume_24h = json.data.quotes.USD.total_volume_24h;
 			last_updated = json.data.last_updated;
			
 			let embed = new Discord.RichEmbed()
 			.setAuthor("Coinmarketcap", "http://icons.iconarchive.com/icons/froyoshark/enkel/256/Bitcoin-icon.png")
            .addField("Market Cap (USD):", numberFormat(total_market_cap))
            .addField("24h Vol (USD): ", numberFormat(total_volume_24h))
            .addField("BTC Dominance(%): ", bitcoin_percentage_of_market_cap)            
            .setFooter("Last Updated: " + timeConverter(last_updated))
            .setColor("AQUA");

        // Send the embed with message.channel.send()
        message.channel.send({embed: embed}).then(msg=>{msg.delete(10000)}); 
        message.delete(12000);       
    	});    	 
}

Thêm bot vào Server Discord

Open link & thay bằng client_id của bạn trên trình duyệt

Khởi chạy bot

node bot.js

Demo

 

Source code:  GitHub

Chúc các bạn thành công

DONATE

Bitcoin address: 1tmxPQbmycQMehAAZ8FshbvEoQZ6Ri7PT

ETH Address: 0xfe17aaf16bceb4311795b2e8ff0199640bdce54a

ETC Address: 0xfe17aaf16bceb4311795b2e8ff0199640bdce54a

XVG Address: D9iP7fhKbHJKViwUG9MWcAt3JPdCuxnCZJ

binance price alert, coin watchlists using c#

Ứng dụng theo dõi giá của coin trên sàn Binance & thông báo khi đạt mức giá quy định.

Lấy danh sách coin trên Binance

var listSymbol = new List();
            using (var client = new BinanceClient())
            {
                var rs = await client.GetAllPricesAsync();
                if (rs.Success && rs.Data != null)
                {
                    foreach (var item in rs.Data)
                    {
                        listSymbol.Add(new SelectListItem
                        {
                            Value = item.Symbol,
                            Text = item.Symbol + " " + item.Price
                        });
                    }
                }
            }

 

Tham khảo: https://github.com/JKorf/Binance.Net

Source code: https://github.com/tuanitpro/binance-price-alert

Hướng dẫn tạo Toggle (Collapsible) ẩn/hiện trong Angular 4

Khi thiết kế website chúng ta hay có nhu cầu ẩn hiện một div / panel, hay một vùng dữ liệu nào đó. Khi người dùng bấm vào sẽ hiển thị nội dung, giúp tiết kiệm không gian hiển thị.

Link demo trên W3school, sử dụng Bootstrap. Link

Trong phạm vi bài viết này chúng ta sẽ thực hiện nó trên angular4. Chúng ta sẽ viết một component để tùy ý sử dụng, viết một lần dùng ở nhiều nơi.

Demo 

Tạo  component collapsible.component với 2 file là collapsible.component.html & collapsible.component.ts

Code file HTML

<section id="tuanitpro_collapse">
  <div class="filter">
    <a (click)="toggleCollapse()" title="Click để đóng mở">{{title || 'Tìm kiếm'}}
    <i class="fa fa-times" *ngIf="!isCollapseOpen"></i>
    <i class="fa fa-search" *ngIf="isCollapseOpen"></i>
  </a>
  </div>
  <div class="filter_panel" [hidden]="isCollapseOpen">
    <div class="x_panel">
      <div class="x_content">
        <ng-content></ng-content>
      </div>
    </div>
  </div>
</section>

Code file .ts

import { Component, OnInit, Input, AfterViewInit, ChangeDetectorRef } from '@angular/core';

@Component({
  selector: 'app-collapsible',
  templateUrl: './collapsible.component.html'
})
export class CollapsibleComponent implements OnInit, AfterViewInit {
  @Input() title: string;
  @Input() uid: string;

  public isCollapseOpen = true;
  constructor(private ref: ChangeDetectorRef) { }

  ngOnInit() {
  }
  ngAfterViewInit() {
    const savedState = localStorage.getItem(this.uid + '_filterKey');
    if (savedState) {
      if (savedState === 'true') {
        this.isCollapseOpen = true;
      } else {
        this.isCollapseOpen = false;
      }
    }
    this.ref.detectChanges();

  }
  toggleCollapse() {
    const currentState = this.isCollapseOpen;
    this.isCollapseOpen = !currentState;
    localStorage.setItem(this.uid + '_filterKey', String(this.isCollapseOpen));
  }
}

Cách dùng:

import vào app.module.ts

import { CollapsibleComponent } from ‘./collapsible.component’;
@NgModule({
declarations: [
CollapsibleComponent
],
Trong UI cần ẩn hiện
<app-collapsible title="Tiêu đề" uid="category">
<div class="panel">
Nội dung cần ẩn hiện
</div>
</app-collapsible>

Chúc các bạn thành công.

Cascading Dropdown Ajax

Chào các bạn

Khi lập trình các bạn hay gặp vấn đề khó khăn khi lấy dữ liệu giữa các Dropdown List khác nhau. Ví dụ: Từ tỉnh thành -> quận huyện -> Xã phường…

Đây là khó khăn của rất nhiều bạn sinh viên khi mới bắt đầu học lập trình. Video dưới đây sẽ hướng dẫn bạn cách giải quyết, khá là đơn giản. Hoàn toàn có thể áp dụng nhiều trường hợp khác nhau.

Video không có tiếng, do mình làm trong lúc ngẫu hứng ngoài quán cafe. Các bạn có thể theo dõi, hoặc tải mã nguồn về phân tích thêm.

Slide giới thiệuhttps://docs.google.com/presentation/d/1soxUWN7Xa6Z89Az-PNCtiyGgMVdVSgmqzp1bf7hdi50/edit?usp=sharing

Tài nguyên

SQL Data:
CSDL tên Quốc gia, tỉnh thành phố thị xã quận huyện, xã phường Việt Nam
Ajax là gì: http://tuanitpro.com/ajax-la-gi Jquery.com asp.net/mvc https://github.com/tuanitpro/cascading-dropdown-ajax-mvc

Demo

Cascading Dropdown Ajax

Code C#

 public class MyDbContext:DbContext
    {
        // Ở đây các bạn có thể khai báo trong Web.config.
        private const string sqlConnection = @"Data Source=.\SQLExpress; Initial Catalog = CountryDb; User Id=sa; Password = sa";

        public MyDbContext() : base(sqlConnection)
        {

        }
      
        public DbSet<Country> Countries { get; set; }
        public DbSet<Province> Provinces { get; set; }
        public DbSet<District> Districts { get; set; }
        public DbSet<Ward> Wards { get; set; }

    }

 

  public JsonResult GetAllCountries()
        {
            using(var db = new MyDbContext())
            {
                var data = db.Countries.OrderBy(x=>x.Name).ToList();
                return Json(data, JsonRequestBehavior.AllowGet);
            }
        }
        /// <summary>
        /// Hàm lấy danh sách tỉnh thành theo CountryId. 
        /// Id = 237 là của Việt Nam. Do database mình quy định vậy
        /// Test OK
        /// </summary>
        /// <param name="id">Id của country</param>
        /// <returns></returns>
        public JsonResult GetAllProvinceByCountryId(int? id=237) 
        {
            using (var db = new MyDbContext())
            {               
                var data = db.Provinces.Where(x=>x.CountryId== id).OrderBy(x=>x.Name).ToList();
                return Json(data, JsonRequestBehavior.AllowGet);
            }
        }
        /// <summary>
        /// Hàm lấy tất cả danh sách quận huyện
        /// Id = 1 là Hà Nội, do database mình quy định vậy
        /// Test OK
        /// </summary>
        /// <param name="id">Id = ProvinceId</param>
        /// <returns></returns>
        public JsonResult GetAllDistrictByProvinceId(int? id = 1)
        {
            using (var db = new MyDbContext())
            {
                var data = db.Districts.Where(x => x.ProvinceId == id).OrderBy(x=>x.Name).ToList();
                return Json(data, JsonRequestBehavior.AllowGet);
            }
        }
        /// <summary>
        /// Hàm lấy danh sách xã phường theo quận huyện
        /// Id= 1 là Ba Đình. Do database quy định
        /// Test OK
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public JsonResult GetAllWardByDistrictId(int? id = 1)
        {
            using (var db = new MyDbContext())
            {
                var data = db.Wards.Where(x => x.DistrictId == id).OrderBy(x=>x.Name).ToList();
                return Json(data, JsonRequestBehavior.AllowGet);
            }
        }

Code js

// File javascript để lấy dữ liệu

// Khai báo URL service của bạn ở đây
var baseService = "/Service";
var countryUrl = baseService + "/GetAllCountries";
var provinceUrl = baseService + "/GetAllProvinceByCountryId";
var districtUrl = baseService + "/GetAllDistrictByProvinceId";
var wardUrl = baseService + "/GetAllWardByDistrictId";
$(document).ready(function () {
    // load danh sách country
    _getCountries();
    $("#ddlCountry").on('change', function () {
        var id = $(this).val();
        if (id != undefined && id != '') {
            _getProvince(id);
        }
    });

    $("#ddlProvince").on('change', function () {
        var id = $(this).val();
        if (id != undefined && id != '') {
            _getDistrict(id);
        }
    });
    $("#ddlDistrict").on('change', function () {
        var id = $(this).val();
        if (id != undefined && id != '') {
            _getWard(id);
        }
    });
    $("#ddlWard").on('change', function () {
        var countryText = $("#ddlCountry option:selected").text();
        var provinceText = $("#ddlProvince option:selected").text();
        var districtText = $("#ddlDistrict option:selected").text();
        var wardText = $("#ddlWard option:selected").text();
        var html = "Quốc gia: " + countryText + " Tỉnh thành: " + provinceText + " " + "Quận huyện: " + districtText + " " + "Xã phường: " + wardText;
        html += "</br>Quê bạn thật là đẹp. Chúc mừng bạn!!!";
        $("#divResult").html(html);
    });
});
function _getCountries() {
    $.get(countryUrl, function (data) {
        if (data != null && data != undefined && data.length) {
            var html = '';
            html += '<option value="">--Không chọn--</option>';
            $.each(data, function (key, item) {
                html += '<option value=' + item.Id + '>' + item.Name + '</option>';
            });
            $("#ddlCountry").html(html);
        }
    });
}
// truyền id của country vào
function _getProvince(id) {
    $.get(provinceUrl + "/"+id, function (data) {
        if (data != null && data != undefined && data.length) {
            var html = '';
            html += '<option value="">--Không chọn--</option>';
            $.each(data, function (key, item) {
                html += '<option value=' + item.Id + '>' + item.Name + '</option>';
            });
            $("#ddlProvince").html(html);
        }
    });
}
// truyền id của province vào
function _getDistrict(id) {
    $.get(districtUrl + "/" + id, function (data) {
        if (data != null && data != undefined && data.length) {
            var html = '';
            html += '<option value="">--Không chọn--</option>';
            $.each(data, function (key, item) {
                html += '<option value=' + item.Id + '>' + item.Name + '</option>';
            });
            $("#ddlDistrict").html(html);
        }
    });
}
// truyền id của district vào
function _getWard(id) {
    $.get(wardUrl + "/" + id, function (data) {
        if (data != null && data != undefined && data.length) {
            var html = '';
            html += '<option value="">--Không chọn--</option>';
            $.each(data, function (key, item) {
                html += '<option value=' + item.Id + '>' + item.Name + '</option>';
            });
            $("#ddlWard").html(html);
        }
    });
}

Chúc các bạn thành công.

Download GitHub

React Native – Create Login Form – Navigation

Chào các bạn

Tiếp tục tìm hiểu cái mới khi rảnh rỗi, ngoài những thứ quen thuộc, nên hôm nay mình tiếp tục thực hiện một App khó hơn bằng React Native. Đó là tạo form đăng ký, đăng nhập. Và một màn hình show ra những câu danh ngôn ý nghĩa.

Trong phần này có sử dụng nhiều phần, nên kiến thức hơi nhiều. Đầu tiên là API đăng ký đăng nhập, mình đã viết bằng MVC, có sử dụng token, mục đích Login, SignUp. Bạn có thể dùng API khác, tùy ý.

Phần thứ 2 là những câu danh ngôn, mình sử dụng API của PHP. Link: http://tuanitpro.com/android/api.php

Các kiến thức cần thiết khác của React Native đó là Navigation, component mới, version cũ sẽ không có, mà có tên là Navigator. Sử dụng để chuyển các màn hình. Ở ví dụ này đơn giản, nên không có truyền tham số khi chuyển trang.

AsyncStorage để lưu thông tin user đăng nhập.
Màn hình SplashScreen
 Code file android.index.js
/**
 * Project Login, SignUp
 * Author Name: Thanh Tuan Le
 * Author Email: [email protected]
 * Author URI: http://tuanitpro.com
 * Author FB: https://facebook.com/tuanitpro
 * Description:
 * This simple App make with love React Native
 * Download source code:
 * https://github.com/tuanitpro/react-native-weather-app
 * Donate: 
 * BTC Address: 1MXE6ZHSkNrZ2s6XYXtFhpgwRc8Hhuc9fr
 * Paypal: https://www.paypal.me/tuanitpro/5
 */

import React, { Component } from 'react';
import {
  AppRegistry,
 
} from 'react-native';
import {
  StackNavigator,
} from 'react-navigation';


 import MainPage from './MainPage.js';
 import SplashPage from './SplashPage.js';
 import LoginPage from './LoginPage.js';
 import ForgotPassPage from './ForgotPassPage.js';
 import SignUpPage from './SignUpPage.js';


const MyApp = StackNavigator({
  SplashPage: { screen: SplashPage },
  MainPage: { screen: MainPage },
  LoginPage: { screen: LoginPage },
  ForgotPassPage: { screen: ForgotPassPage },
  SignUpPage: {screen: SignUpPage}
});
AppRegistry.registerComponent('bookClientApi', () => MyApp);

Code Màn hình đăng ký

 const BASE_URL = "http://ec2-52-27-149-161.us-west-2.compute.amazonaws.com";

let serviceUrl = BASE_URL+  "/api/account/register";
      let userName = this.state.userName;
      let password = this.state.password;
      let confirmPassword = this.state.confirmPassword;
      // kiem tra o day  
    fetch(serviceUrl,{
        method: "POST",          
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },
      body: JSON.stringify({
        'username': userName,
        'password': password,
        'confirmPassword':confirmPassword
      })



        })
          .then((response) => response.json())
          .then((responseJSON) => {  
                if(responseJSON.message=="Success"){
                     var { navigate } = this.props.navigation;
                     navigate('LoginPage');
                    ToastAndroid.show(responseJSON.message, ToastAndroid.SHORT)
                }
          })
          .catch((error) => {
            console.warn(error);
          });

Code Màn hình Login

const BASE_URL = "http://ec2-52-27-149-161.us-west-2.compute.amazonaws.com";

let serviceUrl =  BASE_URL + "/oauth2/token";
      let userName = this.state.userName;
      let password = this.state.password;
      var access_token = '';


      let postData = "grant_type=password&username=" + userName + "&password=" + password;              

        fetch(serviceUrl,{
          method: "POST",
          
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },
              body: postData
        })
          .then((response) => response.json())
          .then((responseJSON) => {  
                
              
                 
               }
               else{
                  Alert.alert('Login failure');
               }
               
          })
          .catch((error) => {
            console.warn(error);
          });

Code màn hình chính

fetch('http://tuanitpro.com/android/api.php',{
          method: "GET",
           
            })
          .then((response) => response.json())
          .then((responseJSON) => {  
                 let dataArray = responseJSON;
               
              
                 var max = dataArray.length;
                 var min  = 1;
                 var randIndex = Math.floor(Math.random() * (max - min + 1)) + min;
                var item = dataArray[randIndex];
                if(item !=undefined){
                  this.setState({
                  quote : item.content,
                  author : item.author
                  });
                  
                }
                console.log(item);

          })
          .catch((error) => {
            console.warn(error);
          });

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  Image,
 ScrollView,
   AsyncStorage,
  TouchableOpacity,
   
} from 'react-native';
var STORAGE_KEY = 'key_access_token';
const background = require('./bg_quotes.jpg') ;

export default class MainPage extends Component {
   static navigationOptions = {
    title: 'Welcome',
    header:null,
  };
    constructor(props) {
    super(props);
  
    this.state = {
      quote: 'Cuộc sống không bao giờ là bế tắc thực sự nếu con người ta dám rời bỏ lối mòn & dũng cảm tìm ra giá trị mới.',
      author: 'Khuyết danh',
    };
  }
  
  componentWillMount() {
    try {
    AsyncStorage.getItem(STORAGE_KEY).then((user_data_json) => {
    let userData = JSON.parse(user_data_json);
        if(userData ==undefined){
              var { navigate } = this.props.navigation;
              navigate('LoginPage');
        }
this._onChangeText();
    });

    } catch (error) {
            console.log('AsyncStorage error: ' + error.message);
    }          

    
     
    }
    _onChangeText(event){
     fetch('http://tuanitpro.com/android/api.php',{
          method: "GET",
           
            })
          .then((response) => response.json())
          .then((responseJSON) => {  
                 let dataArray = responseJSON;
               
              
                 var max = dataArray.length;
                 var min  = 1;
                 var randIndex = Math.floor(Math.random() * (max - min + 1)) + min;
                var item = dataArray[randIndex];
                if(item !=undefined){
                  this.setState({
                  quote : item.content,
                  author : item.author
                  });
                  
                }
                console.log(item);

          })
          .catch((error) => {
            console.warn(error);
          }); 
    }
 _onPressLogOut (event) {
       try {
AsyncStorage.removeItem(STORAGE_KEY);
 
          var { navigate } = this.props.navigation;
          navigate('LoginPage');
} catch (error) {
        console.log('AsyncStorage error: ' + error.message);
}

       
    
 }

 render() {
    return (
        <Image style={[styles.container, styles.background]}
        source = {background}  resizeMode="cover">
        <View style={styles.container}>
 
          <View style={styles.wrapper}>
           <View style={styles.contents}>

 <TouchableOpacity activeOpacity={.5} onPress={this._onChangeText.bind(this)} keyboardShouldPersistTaps={true}>
            <Text style={styles.quotes}>{this.state.quote}</Text>
              <Text style={styles.author}>{this.state.author}</Text>

  </TouchableOpacity> 

      </View>


   </View>
   </View>

   <View style={styles.footer}>
        <TouchableOpacity activeOpacity={.5} onPress={this._onPressLogOut.bind(this)} keyboardShouldPersistTaps={true}>
    <View style={styles.button}>
<Text style={styles.buttonText}> Logout</Text>
      </View>      
      
    </TouchableOpacity> 
   
</View>
       </Image>
    );
  }
  
  
}
 
 
const styles = StyleSheet.create({
  container: {
    flex: 1,
     
  },
  footer: {
  position: 'absolute',
  flex:1,
  left: 0,
  right: 0,
  bottom: -10,
 
},
  background:{
    width: null,
    height:null,
  },
  wrapper:{
      paddingHorizontal:15,
  },
  
button:{
backgroundColor:"#d73352",
paddingVertical: 8,
marginVertical:8,
alignItems: "center",
justifyContent: "center",
},


  buttonText: {
      fontSize: 16,
      color:'#FFFFFF',
      textAlign: 'center',
     
  },
  
  contents:{
        marginTop: 100,        
        backgroundColor: 'rgba(52, 52, 52, 0.3)'
  },
  quotes: {
     fontSize: 18,
    textAlign: 'center',
    color: '#FFFFFF',
    marginBottom: 5,
  },
  author: {
    textAlign: 'right',
    color: '#FFFFFF',
    marginBottom: 5,
  },
});

Các bạn có thể download mã nguồn tại  GitHub

Chúc các bạn thành công.

# Ứng dụng xem thời tiết đơn giản bằng React Native 

Weather app with react-native

Cuối tuần rảnh rỗi, tìm chút gì đó để làm, thoát ra những gì quen thuộc.

Chào các bạn.

React Native là một framework cho phép các lập trình viên xây dựng các ứng dụng trên nền tảng Android và iOS sử dụng ngôn ngữ lập trình javascript nhưng mang lại trải nghiệm native app thực sự.

Continue reading Weather app with react-native