二、RxJava 创建:create,just,fromArray,empty,range

本文通过实例代码详细解析RxJava中常用的五种创建Observable的方法:create、just、fromArray、empty和range。从发射单一值到创建空Observable,再到从数组生成序列,逐一进行演示并打印输出结果。

1.项目地址

在MainActivity3那里

2.讲解

1.普通创建 create:这里发射一个“A”,然后打印出来:

//普通创建:
        Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<String> emitter) throws Throwable {
                emitter.onNext("A");
                emitter.onComplete();
            }
        })
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {

                    }

                    @Override
                    public void onNext(@NonNull String s) {
                        Log.d(TAG, "onNext: "+s);
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });

2.用just创建,这里打印了A,B

这里的

emitter.onNext("A");
emitter.onComplete();

在里面默认执行了

Observable.just("A","B")
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {

                    }

                    @Override
                    public void onNext(@NonNull String s) {
                        Log.d(TAG, "onNext: "+s);
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });

3.用fromArray,来打印string[]里面的值:

String[] strings={"1","2","3"};
       
        Observable.fromArray(strings)
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {

                    }

                    @Override
                    public void onNext(@NonNull String s) {
                        Log.d(TAG, "onNext: "+s);
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
        Log.d(TAG, "onCreate: rxJava:"+l1);

4.用empty来创建(发送不操作)

Observable.empty()
                .subscribe(new Observer<Object>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {

                    }

                    @Override
                    public void onNext(@NonNull Object o) {

                    }

                    @Override
                    public void onError(@NonNull Throwable e) {

                    }

                    @Override
                    public void onComplete() {
                        Log.d(TAG, "onComplete: ");
                    }
                });

5.用range来创建,可以设置第几个开始打印,打印个数

这里从15开始打印,打印五个(15,16,17,18,19)

Observable.range(15,5)//开始打印的值,打印个数
                .subscribe(new Observer<Integer>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {

                    }

                    @Override
                    public void onNext(@NonNull Integer integer) {
                        Log.d(TAG, "onNext: "+integer);
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
帮我分析并注释以下代码 /* sequence.cpp data-sequence class Copyright J Brown 1999-2006 www.catch22.net Freeware */ #include <windows.h> #include <stdarg.h> #include <stdio.h> #include "sequence.h" #ifdef DEBUG_SEQUENCE char debugfile[_MAX_PATH]; void odebug(const char *fmt, ...) { va_list varg; va_start(varg, fmt); char buf[512]; vsprintf(buf, fmt, varg); OutputDebugString(buf); va_end(varg); } void debug(const char *fmt, ...) { FILE *fp; va_list varg; va_start(varg, fmt); if((fp = fopen(debugfile, "a")) != 0) { vfprintf(fp, fmt, varg); fclose(fp); } va_end(varg); } #else #define debug #define odebug #endif sequence::sequence () { record_action(action_invalid, 0); head = tail = 0; sequence_length = 0; group_id = 0; group_refcount = 0; head = new span(0, 0, 0); tail = new span(0, 0, 0); head->next = tail; tail->prev = head; #ifdef DEBUG_SEQUENCE SYSTEMTIME st; GetLocalTime(&st); sprintf(debugfile, "seqlog-%04d%02d%02d-%02d%02d%0d.txt", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); #endif } sequence::~sequence () { clear(); delete head; delete tail; } bool sequence::init () { sequence_length = 0; if(!alloc_modifybuffer(0x10000)) return false; record_action(action_invalid, 0); group_id = 0; group_refcount = 0; undoredo_index = 0; undoredo_length = 0; return true; } bool sequence::init (const seqchar *buffer, size_t length) { clear(); if(!init()) return false; buffer_control *bc = alloc_modifybuffer(length); memcpy(bc->buffer, buffer, length * sizeof(seqchar)); bc->length = length; span *sptr = new span(0, length, bc->id, tail, head); head->next = sptr; tail->prev = sptr; sequence_length = length; return true; } // // Initialize from an on-disk file // bool sequence::open(TCHAR *filename, bool readonly) { return false; } // // Initialize from an on-disk file // //bool sequence::save(TCHAR *filename) //{ // return false; //} template <class type> void sequence::clear_vector (type &vectorobject) { for(size_t i = 0; i < vectorobject.size(); i++) { delete vectorobject[i]; } } void sequence::clearstack (eventstack &dest) { for(size_t i = 0; i < dest.size(); i++) { dest[i]->free(); delete dest[i]; } dest.clear(); } void sequence::debug1 () { span *sptr; for(sptr = head; sptr; sptr = sptr->next) { char *buffer = (char *)buffer_list[sptr->buffer]->buffer; printf("%.*s", sptr->length, buffer + sptr->offset); } printf("\n"); } void sequence::debug2 () { span *sptr; printf("**********************\n"); for(sptr = head; sptr; sptr = sptr->next) { char *buffer = (char *)buffer_list[sptr->buffer]->buffer; printf("[%d] [%4d %4d] %.*s\n", sptr->id, sptr->offset, sptr->length, sptr->length, buffer + sptr->offset); } printf("-------------------------\n"); for(sptr = tail; sptr; sptr = sptr->prev) { char *buffer = (char *)buffer_list[sptr->buffer]->buffer; printf("[%d] [%4d %4d] %.*s\n", sptr->id, sptr->offset, sptr->length, sptr->length, buffer + sptr->offset); } printf("**********************\n"); for(sptr = head; sptr; sptr = sptr->next) { char *buffer = (char *)buffer_list[sptr->buffer]->buffer; printf("%.*s", sptr->length, buffer + sptr->offset); } printf("\nsequence length = %d chars\n", sequence_length); printf("\n\n"); } // // Allocate a buffer and add it to our 'buffer control' list // sequence::buffer_control* sequence::alloc_buffer (size_t maxsize) { buffer_control *bc; if((bc = new buffer_control) == 0) return 0; // allocate a new buffer of byte/wchar/long/whatever if((bc->buffer = new seqchar[maxsize]) == 0) { delete bc; return 0; } bc->length = 0; bc->maxsize = maxsize; bc->id = buffer_list.size(); // assign the id buffer_list.push_back(bc); return bc; } sequence::buffer_control* sequence::alloc_modifybuffer (size_t maxsize) { buffer_control *bc; if((bc = alloc_buffer(maxsize)) == 0) return 0; modifybuffer_id = bc->id; modifybuffer_pos = 0; return bc; } // // Import the specified range of data into the sequence so we have our own private copy // bool sequence::import_buffer (const seqchar *buf, size_t len, size_t *buffer_offset) { buffer_control *bc; // get the current modify-buffer bc = buffer_list[modifybuffer_id]; // if there isn't room then allocate a new modify-buffer if(bc->length + len >= bc->maxsize) { bc = alloc_modifybuffer(len + 0x10000); // make sure that no old spans use this buffer record_action(action_invalid, 0); } if(bc == 0) return false; // import the data memcpy(bc->buffer + bc->length, buf, len * sizeof(seqchar)); *buffer_offset = bc->length; bc->length += len; return true; } // // sequence::spanfromindex // // search the spanlist for the span which encompasses the specified index position // // index - character-position index // *spanindex - index of span within sequence // sequence::span* sequence::spanfromindex (size_w index, size_w *spanindex = 0) const { span * sptr; size_w curidx = 0; // scan the list looking for the span which holds the specified index for(sptr = head->next; sptr->next; sptr = sptr->next) { if(index >= curidx && index < curidx + sptr->length) { if(spanindex) *spanindex = curidx; return sptr; } curidx += sptr->length; } // insert at tail if(sptr && index == curidx) { *spanindex = curidx; return sptr; } return 0; } void sequence::swap_spanrange(span_range *src, span_range *dest) { if(src->boundary) { if(!dest->boundary) { src->first->next = dest->first; src->last->prev = dest->last; dest->first->prev = src->first; dest->last->next = src->last; } } else { if(dest->boundary) { src->first->prev->next = src->last->next; src->last->next->prev = src->first->prev; } else { src->first->prev->next = dest->first; src->last->next->prev = dest->last; dest->first->prev = src->first->prev; dest->last->next = src->last->next; } } } void sequence::restore_spanrange (span_range *range, bool undo_or_redo) { if(range->boundary) { span *first = range->first->next; span *last = range->last->prev; // unlink spans from main list range->first->next = range->last; range->last->prev = range->first; // store the span range we just removed range->first = first; range->last = last; range->boundary = false; } else { span *first = range->first->prev; span *last = range->last->next; // are we moving spans into an "empty" region? // (i.e. inbetween two adjacent spans) if(first->next == last) { // move the old spans back into the empty region first->next = range->first; last->prev = range->last; // store the span range we just removed range->first = first; range->last = last; range->boundary = true; } // we are replacing a range of spans in the list, // so swap the spans in the list with the one's in our "undo" event else { // find the span range that is currently in the list first = first->next; last = last->prev; // unlink the the spans from the main list first->prev->next = range->first; last->next->prev = range->last; // store the span range we just removed range->first = first; range->last = last; range->boundary = false; } } // update the 'sequence length' and 'quicksave' states std::swap(range->sequence_length, sequence_length); std::swap(range->quicksave, can_quicksave); undoredo_index = range->index; if(range->act == action_erase && undo_or_redo == true || range->act != action_erase && undo_or_redo == false) { undoredo_length = range->length; } else { undoredo_length = 0; } } // // sequence::undoredo // // private routine used to undo/redo spanrange events to/from // the sequence - handles 'grouped' events // bool sequence::undoredo (eventstack &source, eventstack &dest) { span_range *range = 0; size_t group_id; if(source.empty()) return false; // make sure that no "optimized" actions can occur record_action(action_invalid, 0); group_id = source.back()->group_id; do { // remove the next event from the source stack range = source.back(); source.pop_back(); // add event onto the destination stack dest.push_back(range); // do the actual work restore_spanrange(range, source == undostack ? true : false); } while(!source.empty() && (source.back()->group_id == group_id && group_id != 0)); return true; } // // UNDO the last action // bool sequence::undo () { debug("Undo\n"); return undoredo(undostack, redostack); } // // REDO the last UNDO // bool sequence::redo () { debug("Redo\n"); return undoredo(redostack, undostack); } // // Will calling sequence::undo change the sequence? // bool sequence::canundo () const { return undostack.size() != 0; } // // Will calling sequence::redo change the sequence? // bool sequence::canredo () const { return redostack.size() != 0; } // // Group repeated actions on the sequence (insert/erase etc) // into a single 'undoable' action // void sequence::group() { if(group_refcount == 0) { if(++group_id == 0) ++group_id; group_refcount++; } } // // Close the grouping // void sequence::ungroup() { if(group_refcount > 0) group_refcount--; } // // Return logical length of the sequence // size_w sequence::size () const { return sequence_length; } // // sequence::initundo // // create a new (empty) span range and save the current sequence state // sequence::span_range* sequence::initundo (size_w index, size_w length, action act) { span_range *event = new span_range ( sequence_length, index, length, act, can_quicksave, group_refcount ? group_id : 0 ); undostack.push_back(event); return event; } sequence::span_range* sequence::stackback(eventstack &source, size_t idx) { size_t length = source.size(); if(length > 0 && idx < length) { return source[length - idx - 1]; } else { return 0; } } void sequence::record_action (action act, size_w index) { lastaction_index = index; lastaction = act; } bool sequence::can_optimize (action act, size_w index) { return (lastaction == act && lastaction_index == index); } // // sequence::insert_worker // bool sequence::insert_worker (size_w index, const seqchar *buf, size_w length, action act) { span * sptr; size_w spanindex; size_t modbuf_offset; span_range newspans; size_w insoffset; if(index > sequence_length) return false; // find the span that the insertion starts at if((sptr = spanfromindex(index, &spanindex)) == 0) return false; // ensure there is room in the modify buffer... // allocate a new buffer if necessary and then invalidate span cache // to prevent a span using two buffers of data if(!import_buffer(buf, length, &modbuf_offset)) return false; debug("Inserting: idx=%d len=%d %.*s\n", index, length, length, buf); clearstack(redostack); insoffset = index - spanindex; // special-case #1: inserting at the end of a prior insertion, at a span-boundary if(insoffset == 0 && can_optimize(act, index)) { // simply extend the last span's length span_range *event = undostack.back(); sptr->prev->length += length; event->length += length; } // general-case #1: inserting at a span boundary? else if(insoffset == 0) { // // Create a new undo event; because we are inserting at a span // boundary there are no spans to replace, so use a "span boundary" // span_range *oldspans = initundo(index, length, act); oldspans->spanboundary(sptr->prev, sptr); // allocate new span in the modify buffer newspans.append(new span( modbuf_offset, length, modifybuffer_id) ); // link the span into the sequence swap_spanrange(oldspans, &newspans); } // general-case #2: inserting in the middle of a span else { // // Create a new undo event and add the span // that we will be "splitting" in half // span_range *oldspans = initundo(index, length, act); oldspans->append(sptr); // span for the existing data before the insertion newspans.append(new span( sptr->offset, insoffset, sptr->buffer) ); // make a span for the inserted data newspans.append(new span( modbuf_offset, length, modifybuffer_id) ); // span for the existing data after the insertion newspans.append(new span( sptr->offset + insoffset, sptr->length - insoffset, sptr->buffer) ); swap_spanrange(oldspans, &newspans); } sequence_length += length; return true; } // // sequence::insert // // Insert a buffer into the sequence at the specified position. // Consecutive insertions are optimized into a single event // bool sequence::insert (size_w index, const seqchar *buf, size_w length) { if(insert_worker(index, buf, length, action_insert)) { record_action(action_insert, index + length); return true; } else { return false; } } // // sequence::insert // // Insert specified character-value into sequence // bool sequence::insert (size_w index, const seqchar val) { return insert(index, &val, 1); } // // sequence::deletefromsequence // // Remove + delete the specified *span* from the sequence // void sequence::deletefromsequence(span **psptr) { span *sptr = *psptr; sptr->prev->next = sptr->next; sptr->next->prev = sptr->prev; memset(sptr, 0, sizeof(span)); delete sptr; *psptr = 0; } // // sequence::erase_worker // bool sequence::erase_worker (size_w index, size_w length, action act) { span *sptr; span_range oldspans; span_range newspans; span_range *event; size_w spanindex; size_w remoffset; size_w removelen; bool append_spanrange; debug("Erasing: idx=%d len=%d\n", index, length); // make sure we stay within the range of the sequence if(length == 0 || length > sequence_length || index > sequence_length - length) return false; // find the span that the deletion starts at if((sptr = spanfromindex(index, &spanindex)) == 0) return false; // work out the offset relative to the start of the *span* remoffset = index - spanindex; removelen = length; // // can we optimize? // // special-case 1: 'forward-delete' // erase+replace operations will pass through here // if(index == spanindex && can_optimize(act, index)) { event = stackback(undostack, act == action_replace ? 1 : 0); event->length += length; append_spanrange = true; if(frag2 != 0) { if(length < frag2->length) { frag2->length -= length; frag2->offset += length; sequence_length -= length; return true; } else { if(act == action_replace) stackback(undostack, 0)->last = frag2->next; removelen -= sptr->length; sptr = sptr->next; deletefromsequence(&frag2); } } } // // special-case 2: 'backward-delete' // only erase operations can pass through here // else if(index + length == spanindex + sptr->length && can_optimize(action_erase, index+length)) { event = undostack.back(); event->length += length; event->index -= length; append_spanrange = false; if(frag1 != 0) { if(length < frag1->length) { frag1->length -= length; frag1->offset += 0; sequence_length -= length; return true; } else { removelen -= frag1->length; deletefromsequence(&frag1); } } } else { append_spanrange = true; frag1 = frag2 = 0; if((event = initundo(index, length, act)) == 0) return false; } // // general-case 2+3 // clearstack(redostack); // does the deletion *start* mid-way through a span? if(remoffset != 0) { // split the span - keep the first "half" newspans.append(new span(sptr->offset, remoffset, sptr->buffer)); frag1 = newspans.first; // have we split a single span into two? // i.e. the deletion is completely within a single span if(remoffset + removelen < sptr->length) { // make a second span for the second half of the split newspans.append(new span( sptr->offset + remoffset + removelen, sptr->length - remoffset - removelen, sptr->buffer) ); frag2 = newspans.last; } removelen -= min(removelen, (sptr->length - remoffset)); // archive the span we are going to replace oldspans.append(sptr); sptr = sptr->next; } // we are now on a proper span boundary, so remove // any further spans that the erase-range encompasses while(removelen > 0 && sptr != tail) { // will the entire span be removed? if(removelen < sptr->length) { // split the span, keeping the last "half" newspans.append(new span( sptr->offset + removelen, sptr->length - removelen, sptr->buffer) ); frag2 = newspans.last; } removelen -= min(removelen, sptr->length); // archive the span we are replacing oldspans.append(sptr); sptr = sptr->next; } // for replace operations, update the undo-event for the // insertion so that it knows about the newly removed spans if(act == action_replace && !oldspans.boundary) stackback(undostack, 0)->last = oldspans.last->next; swap_spanrange(&oldspans, &newspans); sequence_length -= length; if(append_spanrange) event->append(&oldspans); else event->prepend(&oldspans); return true; } // // sequence::erase // // "removes" the specified range of data from the sequence. // bool sequence::erase (size_w index, size_w len) { if(erase_worker(index, len, action_erase)) { record_action(action_erase, index); return true; } else { return false; } } // // sequence::erase // // remove single character from sequence // bool sequence::erase (size_w index) { return erase(index, 1); } // // sequence::replace // // A 'replace' (or 'overwrite') is a combination of erase+inserting // (first we erase a section of the sequence, then insert a new block // in it's place). // // Doing this as a distinct operation (erase+insert at the // same time) is really complicated, so I just make use of the existing // sequence::erase and sequence::insert and combine them into action. We // need to play with the undo stack to combine them in a 'true' sense. // bool sequence::replace(size_w index, const seqchar *buf, size_w length, size_w erase_length) { size_t remlen = 0; debug("Replacing: idx=%d len=%d %.*s\n", index, length, length, buf); // make sure operation is within allowed range if(index > sequence_length || MAX_SEQUENCE_LENGTH - index < length) return false; // for a "replace" which will overrun the sequence, make sure we // only delete up to the end of the sequence remlen = min(sequence_length - index, erase_length); // combine the erase+insert actions together group(); // first of all remove the range if(remlen > 0 && index < sequence_length && !erase_worker(index, remlen, action_replace)) { ungroup(); return false; } // then insert the data if(insert_worker(index, buf, length, action_replace)) { ungroup(); record_action(action_replace, index + length); return true; } else { // failed...cleanup what we have done so far ungroup(); record_action(action_invalid, 0); span_range *range = undostack.back(); undostack.pop_back(); restore_spanrange(range, true); delete range; return false; } } // // sequence::replace // // overwrite with the specified buffer // bool sequence::replace (size_w index, const seqchar *buf, size_w length) { return replace(index, buf, length, length); } // // sequence::replace // // overwrite with a single character-value // bool sequence::replace (size_w index, const seqchar val) { return replace(index, &val, 1); } // // sequence::append // // very simple wrapper around sequence::insert, just inserts at // the end of the sequence // bool sequence::append (const seqchar *buf, size_w length) { return insert(size(), buf, length); } // // sequence::append // // append a single character to the sequence // bool sequence::append (const seqchar val) { return append(&val, 1); } // // sequence::clear // // empty the entire sequence, clear undo/redo history etc // bool sequence::clear () { span *sptr, *tmp; // delete all spans in the sequence for(sptr = head->next; sptr != tail; sptr = tmp) { tmp = sptr->next; delete sptr; } // re-link the head+tail head->next = tail; tail->prev = head; // delete everything in the undo/redo stacks clearstack(undostack); clearstack(redostack); // delete all memory-buffers for(size_t i = 0; i < buffer_list.size(); i++) { delete[] buffer_list[i]->buffer; delete buffer_list[i]; } buffer_list.clear(); sequence_length = 0; return true; } // // sequence::render // // render the specified range of data (index, len) and store in 'dest' // // Returns number of chars copied into destination // size_w sequence::render(size_w index, seqchar *dest, size_w length) const { size_w spanoffset = 0; size_w total = 0; span *sptr; // find span to start rendering at if((sptr = spanfromindex(index, &spanoffset)) == 0) return false; // might need to start mid-way through the first span spanoffset = index - spanoffset; // copy each span's referenced data in succession while(length && sptr != tail) { size_w copylen = min(sptr->length - spanoffset, length); seqchar *source = buffer_list[sptr->buffer]->buffer; memcpy(dest, source + sptr->offset + spanoffset, copylen * sizeof(seqchar)); dest += copylen; length -= copylen; total += copylen; sptr = sptr->next; spanoffset = 0; } return total; } // // sequence::peek // // return single element at specified position in the sequence // seqchar sequence::peek(size_w index) const { seqchar value; return render(index, &value, 1) ? value : 0; } // // sequence::poke // // modify single element at specified position in the sequence // bool sequence::poke(size_w index, seqchar value) { return replace(index, &value, 1); } // // sequence::operator[] const // // readonly array access // seqchar sequence::operator[] (size_w index) const { return peek(index); } // // sequence::operator[] // // read/write array access // sequence::ref sequence::operator[] (size_w index) { return ref(this, index); } // // sequence::breakopt // // Prevent subsequent operations from being optimized (coalesced) // with the last. // void sequence::breakopt() { lastaction = action_invalid; }
最新发布
07-02
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值