github.com/indiespirit/react-native-chart-kit

 

indiespirit/react-native-chart-kit

📊React Native Chart Kit: Line Chart, Bezier Line Chart, Progress Ring, Bar chart, Pie chart, Contribution graph (heatmap) - indiespirit/react-native-chart-kit

github.com

프로젝트 진행 중 그래프 출력을 해야하는 로직이 있어 react-native-chart-kit 을 사용함. 

 

여러가지 그래프 출력 함수를 제공하지만 가장 기본인 LineChart를 사용하였으며, 그래프 작성시 필요한 값은  datasets->data 배열에 저장해둠.

 

이 data 배열을 동적으로 변경해야하는 경우 아래 코드와 같이 이전 값을 복사 한 뒤 data 배열 값 업데이트 후 setState 함수를 통해 변경된 값을 적용하면 화면이 랜더링 되면서 변경된 값으로 새로운 그래프를 출력함. 

[state내 선언된 LineChart 관련 변수]
[LineChart data 동적 변경 코드]

'0x001 Programming > 03. React-Native' 카테고리의 다른 글

android:usesCleartextTraffic 관련  (0) 2020.06.25
LifeCycle API  (0) 2019.04.29
props | state  (0) 2019.04.29
React Native UI 학습  (0) 2019.03.25

단말(안드로이드) <-> 서버 통신을 통해 인증 및 데이터를 송수신 하는 App 을 개발하던 중 특정 단말기(안드로이드)에서 통신이 안되는 문제가 발생하여 원인을 찾던중 안드로이드 9.0 파이(Pie)로 업데이트 되면서 API 주소, 이미지 주소 등 네트워크 경로가 https 가 아닌 http로 되어 있기 때문에 발생하는 문제로 확인됨. 

 

안드로이드 9.0 파이는 https 를 사용하도록 강제하며 주소가 http인 경우 통신이 안되는 문제가 발생하여 해결 방법을 정리 하고자 함. 

 

해결 방법 1 

 

 => App 내에서 통신에 사용되는 주소를 http -> https 로 변경한다. 

 

해결 방법 2

 

 => res/xml/network_security_config.xml 파일을 생성하고 하단 내용을 기입한다. 

network_security_config.xml

  => AndroidManifest.xml 파일을 아래 처럼 변경한다. 

AndroidManifest.xml

해결 방법 3

 

 => AndroidManifest.xml 파일에 usesCleartextTraffic 관련 옵션을 추가 한다. 

AndroidManifest.xml 

해결 방법은 대략 3가지 정도가 있는것으로 확인 했으며 해당 프로젝트는 3번 방법을 통해 통신이 정상 작동 하는것을 확인 했지만 1번 방법이 가장 좋을것 같아 추후에 API 주소를 변경하고자 함. 

 

출처 : https://stackoverflow.com/questions/45940861/android-8-cleartext-http-traffic-not-permitted

'0x001 Programming > 03. React-Native' 카테고리의 다른 글

react-native-chart-kit LineChart Data 동적 변경  (0) 2020.12.09
LifeCycle API  (0) 2019.04.29
props | state  (0) 2019.04.29
React Native UI 학습  (0) 2019.03.25

LifeCycle API는 컴포넌트가 브라우저에 나타날때, 사라질때, 업데이트 될때 호출되는 API를 말한다. 

 

1. constructor

  => 컴포넌트가 새로 만들어 질때 호출되는 함수 

 

2. componentWillMount

  => 컴포넌트가 화면에 출력되기 직전에 호출되는 함수. v16.3 에서는 해당 API가 deprecated 됨.

 

3. componentDidMount

  => 컴포넌트가 화면에 출력될때 호출되는 함수. 외부 라이브러리 연동 및 데이터 요청등에 주로 사용.

 

4. componentWillReceiveProps 

  => 새로운 props를 받게 되었을때 호출. 주로 state -> props에 따라 변해야 하는 로직을 작성함. 새로 받게될 props는 nextProps로 조회 가능 하며 this.props는 변경전 값임. 

 

5. componentWillUnmount

  => 등록한 이벤트 제거 및 사용한 라이브러리 dispose등 호출하는데 이용함.

'0x001 Programming > 03. React-Native' 카테고리의 다른 글

react-native-chart-kit LineChart Data 동적 변경  (0) 2020.12.09
android:usesCleartextTraffic 관련  (0) 2020.06.25
props | state  (0) 2019.04.29
React Native UI 학습  (0) 2019.03.25

1. props 

  => 부모 컴포넌트가 자식 컴포넌트에게 주는 값. 자식 컴포넌트는 받아온 props 값 수정 불가 

  => 받아온 값은 this. 키워드를 통해 확인 가능함.

  => static defaultProps 를 통해 기본 props 설정 가능 

  

 

2. state 

  => 컴포넌트 내부에서 선언하며 내부에서 값 변경 가능함. 

  => state = { 변수 : 값} 형태로 선언함.

  => state 값을 변경하고 싶은 경우 this.setState 를 사용. 해당 함수를 거치면 컴포넌트가 렌더링 되도록 설계 되어 있음.

 

 

'0x001 Programming > 03. React-Native' 카테고리의 다른 글

react-native-chart-kit LineChart Data 동적 변경  (0) 2020.12.09
android:usesCleartextTraffic 관련  (0) 2020.06.25
LifeCycle API  (0) 2019.04.29
React Native UI 학습  (0) 2019.03.25

1. let / const 

  => const 로 변수를 정의하면 해당 변수에는 값을 재할당 할 수 없다. 

  => let 또는 var로 선언된 변수는 재할당 가능하며, let으로 선언된 변수는 선언된 블록에서만 사용 가능하다.

 

2. 모듈 불러오기 

  => 컴포넌트와 자바스크립 모듈을 내보내기 위해 CommonJS 모듈 문법을 주로 사용 하지만 ES6 모듈 문법에서는 export 와 import 문법을 사용한다.

  => import Component from 'Path'

       class MyComponent extends Component{

      .....

      } 

       export default MyComponent;

 

3. 비 구조화 

  => react는 import 할때 리액트 객체 자체가 넘어 온다. 

    import React from "react";

    let Component = React.Component; 를 아래 문법으로 대체할 수 있다. 

  => import React, {Component} from "react";

https://github.com/facebook/react-native/tree/master/RNTester

 

리액트 네이티브가 지원하는 모든 UI 요소를 살펴볼수 있다.

 

꼭 분석 해볼것!!

'0x001 Programming > 03. React-Native' 카테고리의 다른 글

react-native-chart-kit LineChart Data 동적 변경  (0) 2020.12.09
android:usesCleartextTraffic 관련  (0) 2020.06.25
LifeCycle API  (0) 2019.04.29
props | state  (0) 2019.04.29

typedef struct _IMAGE_EXPORT_DIRECTORY
{
    DWORD Characteristics
    DWORD TimeDateStamp
    WORD MajorVersion
    WORD MinorVersion
    DWORD Name
    DWORD Base
    DWORD NumberOfFunctions
    DWORD NumberOfNames
    DWORD AddressOfFunctions   // 함수 주소 배열(EAX)
    DWORD AddressOfNames    //함수명 배열
    DWORD AddressOfNameOrdinals  //함수 서수 배열
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY

 

 

1) 함수명 배열로 이동하여 원하는 함수의 이름과 해당 인덱스를 찾는다.
2) Ordinals 배열에서 인덱스에 해당하는 서수 인덱스 값을 찾는다.
3) EAT 배열에서 서수 인덱스에 해당하는 함수 offset을 확인한다.
4) DLL Base 주소와 offset을 합해 함수의 실제 주소 값을 구한다. 

'0x001 Programming > 01. C | C++' 카테고리의 다른 글

[Example] 생산자 | 소비자  (0) 2017.12.29
[Tip] 동기화  (0) 2017.12.29
[Tip] Thread 사용시 주의 사항  (0) 2017.12.29
[Tip] 프로세스 관리  (0) 2017.12.29
[Example] 이진 검색 트리를 이용한 파일 정렬  (0) 2017.12.29

import sys
from ctypes import *

 

if __name__ == "__main__":

    target_dll = sys.argv[1]
    target_function = sys.argv[2]
    kernel32 = windll.kernel32

    dll = windll.LoadLibrary(target_dll)

    function = kernel32.GetProcAddress(dll._handle, target_function)

    print "[#] Find Address %s(%s) : 0x%08x" % ( target_dll, target_function, function )

 

사용 방법 : python function.py [Library] [Function]

#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <malloc.h>
#include <io.h>
#include <process.h>
#include <time.h>

 

#define DATA_SIZE 256

 

#ifdef _UNICODE
#define _tstrrchr wcsrchr
#else
#define _tstrrchr strrchr
#endif

 

#ifdef _UNICODE
#define _tstrstr wcsstr
#else
#define _tstrstr strstr
#endif

 

#ifdef _UNICODE
#define _memtchr wmemchr
#else
#define _memtchr memchr
#endif


typedef struct MSG_BLOCK_TAG
{
 CRITICAL_SECTION mGuard;
 DWORD fReady, fStop;
 volatile DWORD nCons, mSequence;
 DWORD nLost;
 time_t mTimestamp;
 DWORD mChecksum;
 DWORD mData[DATA_SIZE];

} MSG_BLOCK;

 

MSG_BLOCK mBlock = {0,0,0,0,0};

 

unsigned int WINAPI Produce (void *);
unsigned int WINAPI Consume(void *);
void MessageFill (MSG_BLOCK *);
void MessageDisplay( MSG_BLOCK *);

 

DWORD _tmain( DWORD argc, LPTSTR argv[] )
{
 DWORD status;
 HANDLE hProduce, hConsume;

 InitializeCriticalSection( &mBlock.mGuard );
 
 hProduce = (HANDLE) _beginthreadex( NULL, 0, Produce, NULL, 0, NULL );
 hConsume = (HANDLE) _beginthreadex( NULL, 0, Consume, NULL, 0, NULL );

 status = WaitForSingleObject( hConsume, INFINITE );
 status = WaitForSingleObject( hProduce, INFINITE );

 DeleteCriticalSection ( &mBlock.mGuard );

 _tprintf(_T("Producer and consumer thread have terminated \n"));
 _tprintf(_T("Message produced : %d, Consumed : %d Lost : %d \n"), mBlock.mSequence, mBlock.nCons, mBlock.mSequence - mBlock.nCons );
 
 return 0;

}

 

unsigned int WINAPI Produce (void * arg)
{
 srand ( (unsigned int) time(NULL) );
 
 while( !mBlock.fStop )
 {
  Sleep(rand() / 100 );

  EnterCriticalSection( &mBlock.mGuard );

  __try
  {
   if( !mBlock.fStop )
   {
    mBlock.fReady = 0;
    MessageFill( &mBlock );
    mBlock.fReady = 1;
    InterlockedIncrement( &mBlock.mSequence );
   }
  }
  __finally
  {
   LeaveCriticalSection ( &mBlock.mGuard );
  }

  
 }

 return 0;
}

 

unsigned int WINAPI Consume( void * arg )
{
 CHAR command, extra;

 while( !mBlock.fStop )
 {
  _tprintf(_T("\n ** Enter 'c' for Consume; 's' to Stop : "));
  _tscanf("%c%c", &command, &extra);

  if( command == 's' )
  {
   mBlock.fStop = 1;
  }
  else if( command == 'c' )
  {
   EnterCriticalSection( &mBlock.mGuard );
   
   __try
   {
    if( mBlock.fReady == 0)
    {
     _tprintf(_T("No New Message. Try Again later \n"));
    }
    else
    {
     MessageDisplay(&mBlock );
     mBlock.nLost = mBlock.mSequence - mBlock.nCons + 1;
     mBlock.fReady = 0;
     InterlockedIncrement( &mBlock.nCons );
    }
   }
   __finally
   {
    LeaveCriticalSection( &mBlock.mGuard );
   }
  }
  else
  {
   _tprintf(_T("Illegal Command, Try Again \n"));
  }

 }

 return 0;
}

 

void MessageFill( MSG_BLOCK * msgBlock)
{
 DWORD i;
 msgBlock->mChecksum = 0;

 for( i = 0; i< DATA_SIZE; i++)
 {
  msgBlock->mData[i] = rand();
  msgBlock->mChecksum ^= msgBlock->mData[i];
 }

 msgBlock->mTimestamp = time( NULL );

 return;

}

 

void MessageDisplay( MSG_BLOCK * msgBlock )
{
 DWORD i, tcheck = 0;

 for( i = 0; i < DATA_SIZE; i++)
 {
  tcheck ^= msgBlock->mData[i];
 }

 _tprintf(_T("\n Message number %d generated at : %s \n"), msgBlock->mSequence, _tctime( &( msgBlock->mTimestamp )));
 _tprintf(_T("First and last entries : %x %x \n"), msgBlock->mData[0], msgBlock->mData[DATA_SIZE - 1 ]);

 if( tcheck == msgBlock->mChecksum )
 {
  _tprintf(_T("GOOD -> mChecksum was validated. \n"));
 }
 else
 {
  _tprintf(_T("BAD -> mCheckSum failed. message Corrupted \n"));
 }

 return;

}

다중 스레드 환경에서 코드가 정상적으로 동작하기 위한 기본 지침은 다음과 같다.
 1) 각 스레드에서만 사용할 변수는 전역 변수가 아니어야 한다. 개별 스레드만 접근 할 수 있도록 자료구조 또는 TLS에 두어야 한다.
 2) 한 함수를 여러 스레드들이 호출하여 어떠한 스레드 고유의 상태 값이 여러 호출들에 걸쳐서 유지되어야 하는 경우 그 상태 값을 전역 변수나 전역 자료구조에 저장하지 말고 TLS나 해당 스레드의 고유한 자료구조에 저장해야 한다.
 3) 스레드를 일시 정지 상태로 생성하지 않는 경우 초기화되지 않은 변수들 같은 경쟁 조건을 피해야 한다.
 4) 스레드가 표준 입력, 출력 핸들들을 설정한다거나 환경 변수들을 변경하는 일은 하지 말아야 한다. 기본 스레드가 다른 어떤 스레드들을 생성하기 전에 환경을 변경한다면 모든 스레드는 동일한 관경을 고유하게 된다. 
 5) 모든 스레드가 공유하는 변수는 정적 또는 전역 저장소에 있어야 하며, 메모리 장벽을 생성하는 동기화 또는 상호잠금 메커니즘들로 변수를 보호해야한다.

1. CRITICAL_SECTION 
  CRITICAL_SECTION 객체는 초기화 되고 삭제되지만 핸들을 가지지는 않으며, 다른 프로세스들과 공유할 수도 없다. CRITICAL_SECTION 형식의 한 변수는 하나의 임계코드 영역을 대표한다. 스레드들은 이 변수를 통해 임계 코드 영역으로 들어가거나 영역에서 벗어난다. 한 시점에서 특정 CRITICAL_SECTION 에는 하나의 스레드만 존재할 수 있다. CRITICAL_SECTION 변수와 관련 자원들을 초기화 하고 삭제할때는 각각 InitializeCriticalSection 함수와 DeleteCriticalSection 함수를 사용한다. EnterCriticalSection 호출이 반환되면 스레드는 임계 영역에 진입한 것이며 이를 스레드가 CRITICAL_SECTION 을 소유했다라고 한다. LeaveCriticialSection 을 호출하면 CRITICAL_SECTION 에 대한 소유권이 해제되고 스레드가 임계영역에서 벗어난다. CRITICAL_SECTION 의 소유권은 반드시 반환해야 한다. 그렇지 않으면 다른 스레드가 영원히 기다리게 된다. 소유한 스레드가 종료되더라고 소유권은 자동으로 반환되지 않으며 __finally 블록을 이용하여 정리 하는 방법을 권장한다. CRITICAL_SECTION 은 커널 객체가 아니라는 장점과 사용자 공간에서 관리된다는 장점이 있다. 비슷한 기능을 가진 Windows 뮤텍스 커널 객체에 비해 거의 항상 성능상의 이점을 제공한다.

2. 뮤텍스(Mutex)
  Mutual Exclusion(상호 배제) 의 준말인 Mutex 는 CRITICAL_SECTION 이상의 잠금 기능성을 제공한다. 뮤텍스에는 이름을 붙일 수 있고 핸들도 있기 때문에 서로 다른 프로세스의 스레드들 사이의 프로세스 간 동기화에 이용할 수 있다. CRITICAL_SECTION 에 비해 뮤텍스는 만료시간을 지정할 수 있으며 프로세스가 종료되었을때 신호될 수 있다는 장점이 있다.

3. 뮤텍스 vs CRITICAL_SECTION 
 1) 두 객체 모두 한 스레드가 객체를 소유하고 있으면 다른 스레드들은 객체가 해제될 때까지 차단된다.
 2)  스레드 종료에 의해 폐기된 뮤텍스는 신호된 상태가 되므로 다른 스레드들이 영원히 차단되는 일이 없다. 하지만 폐기된 뮤텍스가 있다면 프로그램에 심각한 버그나 실패 상황이 존재함이 거의 확실하다.
 3) 뮤텍스는 대기 만료 시간을 지정할 수 있다. CRITICAL_SECTION 은 주기적으로 점검해야한다.
 4) 뮤텍스는 이름을 가질 수 있으며 서로 다른 프로세스의 스레드들이 공유할 수 있다.
 5) 뮤텍스를 생성할때 스레드가 그 뮤텍스를 즉시 소유하게 할 수 있다.
 6) CRITICAL_SECTION 은 거의 항상 뮤텍스 보다 훨씬 빠르다.

4. 세마포어
  하나의 세마포어는 하나의 횟수가 부여된다. 그 횟수가 0보다 크면 세마포 객체는 신호된 상태이고 횟수가 0이면 신호되지 않은 상태이다. 스레드는 두 가지 대기 함수들 중 하나를 사용해서 보통의 방식대로 세마포어를 기다린다. 대기 스레드가 해제되면 세마포어의 횟수가 1 감소한다. 세마포어 함수는 CreateSemaphore, CreateSemaphoreEx, OpenSemaphore, ReleaseSemaphore 가 있다. 세마포어어 횟수를 한번에 2 감소시키는 방법은 존재하지 않기 때문에 CRITICAL_SECTION 을 이용하여 구현해야 한다.

5. 이벤트
  이벤트는 어떠한 조건( 사용 가능한 메시지가 있음 ) 이 이제 성립함을 다른 스레드들에게 신호하는데 쓰인다. 한 이벤트가 신호되었을 때 그것을 기다리는 여러 개 스레드들이 동시에 해제된다. 이벤트는 수동 재설정 이벤트와 자동 재 설정 이벤트로 나뉜다.
  1) 수동 재설정 이벤트는 이벤트를 기다리는 여러 스레드들에게 신호할 수 있다.
  2) 자동 재설정 이벤트는 이벤트를 기다리는 하나의 스레드에게 신호한다. 이벤트는 자동으로 재설정 된다.
  이벤트를 다루는 함수는 CreateEvent, CreateEventEx, OpenEvent, SetEvent, ResetEvent, PulseEvent 이다. SetEvent 는 스레드가 이벤트에 신호를 할 때 쓰인다. 지정된 이벤트가 자동 재설정이면 하나의 대기 스레드가 해제 되며, 이벤트는 자동적으로 신호되지 않은 상태로 돌아간다.

+ Recent posts