Categories
discuss

How do I handle exceptions in map() in an Observable in RxJava

I want to do this:

Observable.just(bitmap)
            .map(new Func1<Bitmap, File>() {
                @Override
                public File call(Bitmap photoBitmap) {

                    //File creation throws IOException, 
                    //I just want it to hit the onError() inside subscribe()

                    File photoFile = new File(App.getAppContext().getCacheDir(), "userprofilepic_temp.jpg");
                    if(photoFile.isFile()) {//delete the file first if it exists otherwise the new file won't be created
                        photoFile.delete();
                    }
                    photoFile.createNewFile(); //saves the file in the cache dir

                    FileOutputStream fos = new FileOutputStream(photoFile);
                    photoBitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);//jpeg format
                    fos.close();

                    return photoFile;

                }
            })
            .subscribe(//continue implementation...);

Basically in the call() method, it can throw exceptions. How can I make the Observer handle it in onError(). Or is this not the right way to think about this?

Answer

rx will always catch error, even if this is RuntimeException. So you can throw Some kind of Runtime exception in catch block. This is how actually it should work.

 Observable.just(bitmap)
                .map(b -> {
                    try {
                        // do some work which throws IOException
                        throw new IOException("something went wrong");
                    } catch (IOException e) {
                        throw new RXIOException(e);
                        // Or you can use 
                        throw Exceptions.propagate(e);
                        // This helper method will wrap your exception with runtime one
                    }
                }).subscribe(o -> {
                    // do something here
                }, exception -> exception.printStackTrace());

public static class RXIOException extends RuntimeException {
        public RXIOException(IOException throwable) {
            super(throwable);
        }
}
Categories
discuss

Robolectric with test.R.java

I’ve got a library project using robolectric 3.0 at API21, with com.android.tools.build:gradle:1.3.1.

I want to use test resources (as if under src/androidTest/res/...), namely com.mypackage.test.R.java (as opposed to com.mypackage.R.java for production) in robolectric tests.

What I have so far:

Directory structure is

src/
  main/
    java
    res
  test/
    java
    // no res here because it's not picked up 
  androidTest/
    res    // picked up by androidTest build variant to generate test.R.java

Then in build.gradle:

android {
  compileSdkVersion 21
  buildToolsVersion = "22.0.1"

  defaultConfig {
    minSdkVersion 15
    targetSdkVersion 21
  }

  sourceSets {
    test {
        java {
            srcDir getTestRJavaDir()
        }
    }
  }
}

def private String getTestRJavaDir(){
  def myManifestRoot = (new XmlParser()).parse("${project.projectDir}/src/main/AndroidManifest.xml")
  def myPackageNamespace = myManifestRoot.@package
  def myPackagePath = myPackageNamespace.replaceAll("\.", "/")

  return "${project.buildDir}/generated/source/r/androidTest/debug/${myPackagePath}/test"
}

afterEvaluate { project ->
  [tasks.compileDebugUnitTestSources, tasks.compileReleaseUnitTestSources]*.dependsOn("compileDebugAndroidTestSources")
}

My tests now successfully compile with test.R.java.

However, at runtime, they fail because robolectric now fails to find my asset files, because they are now located in ${project.buildDir}/intermediates/assets/androidTest/debug whereas previously they were in ${project.buildDir}/intermediates/assets/debug. My suspicion is that robo would also fail to find resource files because they have also been moved under the androidTest (build variant?) directory.

So two questions: 1) is there a better way to do this? 2) if there isn’t, how can I tell robolectric where to look for the asset files?

I’ve tried @Config(assetDir="build/intermediates/assets/androidTest/debug") and @Config(assetDir="../build/intermediates/assets/androidTest/debug") to no avail.

Answer

You can create a custom roboletric test runner like:

public class CustomRobolectricGradleTestRunner extends RobolectricGradleTestRunner {

    public CustomRobolectricGradleTestRunner(Class<?> klass) throws InitializationError {
        super(klass);
    }

    // Fix for the NotFound error with openRawResource()
    @Override
    protected AndroidManifest getAppManifest(Config config) {
        String manifest = "src/main/AndroidManifest.xml";
        String res = String.format("../app/build/intermediates/res/merged/%1$s/%2$s", BuildConfig.FLAVOR, BuildConfig.BUILD_TYPE);
        String asset = "src/test/assets";
        return new AndroidManifest(Fs.fileFromPath(manifest), Fs.fileFromPath(res), Fs.fileFromPath(asset));
    }
}

In the variable asset you can define something like “../build/intermediates/assets/androidTest/debug”

Categories
discuss

React Js onClick inside render

I have a ul li list inside the render method and there is an onClick event on li which call this.handleClick function and state gets changed

var InspirationFilter = React.createClass({
    getInitialState: function() {
        return {currentFilterText:"Top All Time", currentFilter:"top_all_time", showUl:false};
    },
    handleClick: function(filter, filterText){
        this.setState({currentFilterText:filterText, currentFilter:filter, showUl:!this.state.showUl});
    },
    render: function() {
        return (
            <ul>
                <li onClick={this.handleClick('top_all_time', 'Top All Time')}>Top All Time</li>
                  <li onClick={this.handleClick('top_this_week', 'Top This Week')}>Top Week</li>
                <li onClick={this.handleClick('top_this_month', 'Top This Month')}>Top Month</li>
            </ul>
        );
    }
});

But this code gives me the error

Warning: setState(…): Cannot update during an existing state transition (such as within render). Render methods should be a pure function of props and state

I tried to use bind with the click event like this,

return (
    <ul>
        <li onClick={this.handleClick.bind(this,'top_all_time', 'Top All Time')}>Top All Time</li>
        <li onClick={this.handleClick.bind(this,'top_this_week', 'Top This Week')}>Top  Week</li>
        <li onClick={this.handleClick.bind(this.'top_this_month', 'Top This Month')}>Top  Month</li>
    </ul>
);

The above error is gone now but ran into another error which is as follows,

Warning: bind(): You are binding a component method to the component. React does this for you automatically in a high-performance way, so you can safely remove this call. See InspirationFilter

In the react documentation Communicate Between Components they are also using the bind method.

Any suggestions to fix it?

Answer

The problem is that onClick value has to be a function, so just create a helper method that creates such a function for you:

createClickHandler: function(filter, filterText){
    return function() {
        this.setState({...});
    }.bind(this);
},

render: function() {
    return (
        <ul>
            <li onClick={this.createClickHandler('top_all_time', 'Top All Time')}>Top All Time</li>
            <li onClick={this.createClickHandler('top_this_week', 'Top This Week')}>Top Week</li>
            <li onClick={this.createClickHandler('top_this_month', 'Top This Month')}>Top Month</li>
        </ul>
    );
}

React is really just a bit over-helpful here with its warning. Your reason for using bind() is no to bind this, but rather to bind the arguments.

Why it works? This solution avoids the re-binding warning because it’s not re-binding an already bound this.handleClick, but instead creating a new function (that’s not yet bound to anything) and binding that.

Categories
discuss

How to flatten List of Maps in java 8

I have requirement where I have list of maps

[{Men=1},{Men=2, Women=3},{Women=2,Boys=4}]

Now I need make it a flatMap such that it looks like

Gender=countOfValues

In the above example the output would be

{Men=3,Women=5,Boys=4}

Currently I have the following code:

private Map<String, Long> getGenderMap(
        List<Map<String, Long>> genderToCountList) {
    Map<String, Long> gendersMap = new HashMap<String, Long>();
    Iterator<Map<String, Long>> genderToCountListIterator = genderToCountList
            .iterator();
    while (genderToCountListIterator.hasNext()) {
        Map<String, Long> genderToCount = genderToCountListIterator.next();
        Iterator<String> genderToCountIterator = genderToCount.keySet()
                .iterator();
        while (genderToCountIterator.hasNext()) {
            String gender = genderToCountIterator.next();
            if (gendersMap.containsKey(gender)) {
                Long count = gendersMap.get(gender);
                gendersMap.put(gender, count + genderToCount.get(gender));
            } else {
                gendersMap.put(gender, genderToCount.get(gender));
            }
        }
    }
    return gendersMap;
}

How do we write this piece of code using Java8 using lambda expressions?

Answer

I wouldn’t use any lambdas for this, but I have used Map.merge and a method reference, both introduced in Java 8.

Map<String, Long> result = new HashMap<>();
for (Map<String, Long> map : genderToCountList)
    for (Map.Entry<String, Long> entry : map.entrySet())
        result.merge(entry.getKey(), entry.getValue(), Long::sum);

You can also do this with Streams:

return genderToCountList.stream().flatMap(m -> m.entrySet().stream())
           .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, Long::sum));
Categories
discuss

ES6 does for of get prototype values – how to check hasownproperty

Using for...in I always check hasOwnProperty (which I guess is a good argument for using Object.keys) like:

for (let a in obj) {
    if (obj.hasOwnProperty(a)) {
        //logic
    }
}

Do I need to do the same check when I use for...of and if so how should I do it?

According to the MDN page on for...of

While for...in iterates over property names, for...of iterates over property values

But it doesn’t say anything about whether that iteration includes inherited properties or only instance properties. The explanation and example code given there only involve instance properties.

Answer

for...of iterates through an iterable object’s iterator. In the ES6 specification, the function that produces an iterator for an object is identified on an object by the Symbol.iterator property; i.e., someObj[Symbol.iterator].

The iterator returned by Symbol.iterator for each iterable type is different, but generally speaking it will only iterate the values contained by the object that are meaningful relative to the type. For example:

Adding properties to the object’s prototype is unlikely to affect the iterator’s behavior, so in that respect is not necessary to test if the value comes from an own-property or not.

for..of and for..in are fundamentally different. for..in iterates over an object’s properties, and it’s sometimes necessary to ask questions about those properties, like whether they are inherited or not. for..of pumps values out of an iterator, which privately decides what values to return in what order. It’s not necessarily meaningful to ask whether the result of a for..of iteration is from an inherited property or not, because it might not be from a property at all. (Case in point, for..of iteration of a Map returns values that are not exposed as properties.)


I can think of only one (tremendously strange) case in which an inherited property would affect the behavior of an Array iterator, if all the following were true:

  • if Array.prototype has a property with an integer name, and
  • that integer-named property is not set as an own-property on the instance being iterated, and
  • the instance’s length is greater than that integer index’s name

For example:

Array.prototype["7"] = "hello";   // why are you doing this?? :O
var a = [1,2,3]
a.length = 8;                     // why are you doing this?? D:
for(g of a) { console.log(g); }   // great job, you got strange results

In this extremely bizarre case, you would iterate over the inherited 7 property. That’s literally the only case I can think of, though; other inherited properties will be ignored either because they don’t have integer names, or because they’re shadowed by an instance property with the same integer name, or because they are greater or equal to the instance’s length.

Source: stackoverflow
Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Privacy Policy, and Copyright Policy. Content is available under CC BY-SA 3.0 unless otherwise noted. The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 © No Copyrights, All Questions are retrived from public domain..