2016년 7월 26일 화요일

[android] RecyclerView 에서의 setOnItemClickListener (흉내내기)

[개요]


RecyclerView는 ListView에서의 비효율적인 리스트 아이템 생성과 같은 점을 극복하고자 좀 더 유연하고 좀 더 효율적으로 사용되기 위해 만들어졌다고 합니다.
RecyclerView이 만들기 이전에도 ListView에서 ViewHolder개념을 응용? 도입? 해서 효율적으로 사용하였지만 RecyclerView에선 강제적으로 사용하게 되었다고 합니다.

하지만 Listview에서 setOnItemClickListener 와 같은 기능을 지원하지 않습니다.  addOnItemTouchListener와 같은 기능이 있지만 listview에서와 같이 직접적으로 position에 접근을 할 수 없고 여러 이슈가 있다고 합니다.

[흉내내보자]


RecyclerView에서 onBindViewHolder해줄 때에 각각의 아이템에 OnClickListener를 등록해 주는 것으로 접근했습니다.
코드는 핵심적인 부분만 중략해서 작성했습니다.


public class RecyclerAdapter extends RecyclerView.Adapter{
    private ArrayList strings;

    //아이템 클릭시 실행 함수
    private ItemClick itemClick;
    public interface ItemClick {
        public void onClick(View view,int position);
    }

    //아이템 클릭시 실행 함수 등록 함수
    public void setItemClick(ItemClick itemClick) {
        this.itemClick = itemClick;
    }

    public static class ViewHolder extends RecyclerView.ViewHolder{
        View view;
        public ViewHolder(View view) {
            super(view);
            this.view = view;
        }
    }

    @Override
    public RecyclerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                         int viewType) {
        // create a new view
        View v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.list_items, null);
        ViewHolder vh = new ViewHolder(v);

        return vh;
    }


    //중략 ...................

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        final int Position = position;
        //중략 ...................
        holder.view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(itemClick != null){
                    itemClick.onClick(v, Position);
                }
            }
        });
    }
    //중략 ...................

}


adapter 부분에서 이와 같은 방식으로 작성하였습니다.
이후에 recycler 호출부분에서 아래와 같이 작성한다면, listview에서 setOnItemClickListener 와같이 작동할 수 있습니다.

        mAdapter.setItemClick(new RecyclerAdapter.ItemClick() {
            @Override
            public void onClick(View view, int position) {
                //클릭시 실행될 함수 작성
            }
        });

코드가 길어져 상당히 중략을 하였습니다.

제가 작성한 예제 코드는
안드로이드 스터디 프로젝트 git에 공유하고 있습니다.

[java] x초전.., x분전.., x시간전.. 표시하기.

오랫동안의 서버 프로그래밍이 아닌 안드로이드 개발을 시작하면서 만든 함수 입니다.




위와 같은 기능을 만들어 보고 싶었습니다.
생각보다 쉬운 코드라서 별다른 설명이 필요 없을 듯 합니다.
안드로이드 개발을 하며 안들었지만 사용된 함수가 SimpleDateFormat 이기 때문에 java 개발을 하실 때 그냥 사용하시면 되겠습니다.

코드는 여기 에서 보셔도 됩니다.

코드


public class CommonUtil {

    public String beforeTime(Date date){

        Calendar c = Calendar.getInstance();

        long now = c.getTimeInMillis();
        long dateM = date.getTime();

        long gap = now - dateM;

        String ret = "";

//        초       분   시
//        1000    60  60
        gap = (long)(gap/1000);
        long hour = gap/3600;
        gap = gap%3600;
        long min = gap/60;
        long sec = gap%60;

        if(hour > 24){
            ret = new SimpleDateFormat("HH:mm").format(date);
        }
        else if(hour > 0){
            ret = hour+"시간 전";
        }
        else if(min > 0){
            ret = min+"분 전";
        }
        else if(sec > 0){
            ret = sec+"초 전";
        }
        else{
            ret = new SimpleDateFormat("HH:mm").format(date);
        }
        return ret;

    }
}


결과값으로는
x초 전
x분 전
x시간 전
이런식으로 나오게 되고
이외에는 시:분으로 나오게 되는데.
https://developer.android.com/reference/java/text/SimpleDateFormat.html
을 참고하셔서 수정하시면될듯합니다.

2016년 3월 7일 월요일

[redis - node] key event 받아보기

redis key event 받아보기

관련페이지 : http://redis.io/topics/notifications

redis keyspace notification은 2.8버전부터 지원하며 버전 확인은
-> info server  를 통해 확인 가능합니다.

레디스에서는 키 이벤트에 대한 것들의 설정을 하게 되면 pub/sub 패턴을 이용하여 메세지(이벤트)를 전달합니다. 키 이벤트가 발생을 하게 되면 redis서버에서는 keyspace,keyevent의 포맷으로 메세지를 전달합니다.

CONFIG SET nitifi-keyspace-events [option]

를 통해 설정하게 됩니다. options은 위 링크에 나와있습니다. 간단하게
keyspace에 관한 설정은 K
keyevent에 관한 설정은 E
그 뒤의 옵션으로 g, $, l, s, h, z, x, e등이 있으며 A를 통하여 앞의 모든것들 설정가능합니다.각각 옵션에 대한것은 위의 본문 링크를 들어가서 확인하시면 됩니다.

예.. 설명이 빈약합니다. ㅠ
keyspace에 대한 설정을 하게 되면 __keyspace@<db>__[key] 라는 채널로 이벤트가 message로 발행이되고
keyevent에 대한 설정을 하게 되면 __keyevent@<db>__[event] 라는 채널로 key가 message로 발행이됩니다.

받아볼 이벤트의 종류는 g, $, l, s, h, z, x, e, A등을 통하여 설정가능합니다.
예로

CONFIG SET notifiy-keyspace-events KEA

라고 설정을 하게 된다면, 모든 이벤트에 대하여 keyspace,keyevent 채널로 발행이 될것입니다.
제가 맨처음 필요로 했었던 expire에 대한 이벤트의 기준으로만 받아보고 싶다면

CONFIG SET notifiy-keyspace-events Ex

이렇게 설정하면 됩니다.
결과로는

__keyevent@<db>__:expired
의 채널로 키값이 message로 얻어지게 될것입니다.


간단히 redis에서의 pub/sub패턴을 소개하자면 publish,subscript, 즉, 발행, 구독!
레디스에서는 pub/sub를 패턴,채널,메세지의 요소로 나눠 이용합니다.
publisher가 메세지를 해당 채널에 메세지를 전달하게 되면,  패턴에 일치하는 subscriber들이 메세지를 받아보게 됩니다.

pub/sub예제이자 redis notification예제입니다. node입니다.

var redis = require("redis")
  , subscriber = redis.createClient()
  , red  = redis.createClient();

red.config("SET","notify-keyspace-events", "Ex");

subscriber.on("pmessage", function (pattern, channel, message) {
    console.log("pattern : "+pattern+" channel: "+channel+" message : "+message);
});
subscriber.psubscribe("__key*__:*");

red.setex("string key", 10,"string val",redis.print);



결과로는
pattern : __key*__:* channel: __keyevent@0__:expired message : string key

Ex로 설정하였기 때문에 해당 키가 expired된다면 해당 key값을 얻을 수 있습니다.

만약 KEA로 설정을 한다면

pattern : __key*__:* channel: __keyspace@0__:string key message : set
pattern : __key*__:* channel: __keyevent@0__:set message : string key
pattern : __key*__:* channel: __keyspace@0__:string key message : expire
pattern : __key*__:* channel: __keyevent@0__:expire message : string key
---------------------------------------
pattern : __key*__:* channel: __keyspace@0__:string key message : expired
pattern : __key*__:* channel: __keyevent@0__:expired message : string key
이렇게 나옵니다. ㅎ

2016년 1월 25일 월요일

[nodejs - redis] rediss - session 레디스 세션 이용하기

redis를 session서버로 사용하는 방법


session의 값을 server와 분리 시킴으로서 안정적으로 저장하고 여러개의 서버의 세션을 하나의 redis서버로 통합하여 사용 할 수 있습니다. session의 특성상 입출력이 빈번하기 때문에 redis의 성격과도 잘 맞다고 생각됩니다.

우선 환경은
입니다.

레디스 설치 방법은 생략합니다.


//redis session require
var session = require('express-session');
var redis = require('redis');
var redisStore = require('connect-redis')(session);
var client = redis.createClient();

app.use(session(
    {
        secret: 'secret_key',
        store: new redisStore({
            host: "127.0.0.1",
            port: 6379,
            client: client,
            prefix : "session:",
            db : 0
        }),
        saveUninitialized: false, // don't create session until something stored,
        resave: true // don't save session if unmodified
    }
));

//....아래쪽...

//redis session input output
var router = express.Router();
router.get('/session/set/:value', function(req, res) {
    req.session.redSession = req.params.value;
    res.send('session written in Redis successfully');
});

app.get('/session/get/', function(req, res) {
    if(req.session.redSession)
        res.send('the session value stored in Redis is: ' + req.session.redSess);
    else
        res.send("no session value stored in Redis ");
});


를 app.js에 작성하면 설정이 끝나게 됩니다.

new redisStore 부분에 자신의  reids설정을 작성하고 db의 파라미터를 통하여 session store로 사용할 db index를 설정합니다.

prefix를 통하여 키값의 앞에 붙일 값들을 정합니다. redis는 : <- 를 통하여 키값들을 grouping하게 됩니다. 즉, 위와 같이 해놓게 된다면 session에 해당하는 key값들은
아래 결과의 사진을 보게 됬을때 정리가 깔금하게 됩니다.

session의 상용방법은
http://mythinkg.blogspot.kr/2015_01_01_archive.html
를 참고해주시면 됩니다.
단순히 redis에 값을 저장하는 것이기 때문에 사용방법은 express-session과 같고 결과는 아래와 같이 나오는 걸 확인하여 session값이 저장됨을 볼 수있습니다.