Here's what I created to hold the images that my app is currently displaying. Please note that the "Log" object in use here is my custom wrapper around the final Log class inside Android.
package com.wilson.android.library;
/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
import java.io.IOException;
public class DrawableManager {
private final Map<String, Drawable> drawableMap;
public DrawableManager() {
drawableMap = new HashMap<String, Drawable>();
}
public Drawable fetchDrawable(String urlString) {
if (drawableMap.containsKey(urlString)) {
return drawableMap.get(urlString);
}
Log.d(this.getClass().getSimpleName(), "image url:" + urlString);
try {
InputStream is = fetch(urlString);
Drawable drawable = Drawable.createFromStream(is, "src");
if (drawable != null) {
drawableMap.put(urlString, drawable);
Log.d(this.getClass().getSimpleName(), "got a thumbnail drawable: " + drawable.getBounds() + ", "
+ drawable.getIntrinsicHeight() + "," + drawable.getIntrinsicWidth() + ", "
+ drawable.getMinimumHeight() + "," + drawable.getMinimumWidth());
} else {
Log.w(this.getClass().getSimpleName(), "could not get thumbnail");
}
return drawable;
} catch (MalformedURLException e) {
Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
return null;
} catch (IOException e) {
Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
return null;
}
}
public void fetchDrawableOnThread(final String urlString, final ImageView imageView) {
if (drawableMap.containsKey(urlString)) {
imageView.setImageDrawable(drawableMap.get(urlString));
}
final Handler handler = new Handler() {
@Override
public void handleMessage(Message message) {
imageView.setImageDrawable((Drawable) message.obj);
}
};
Thread thread = new Thread() {
@Override
public void run() {
//TODO : set imageView to a "pending" image
Drawable drawable = fetchDrawable(urlString);
Message message = handler.obtainMessage(1, drawable);
handler.sendMessage(message);
}
};
thread.start();
}
private InputStream fetch(String urlString) throws MalformedURLException, IOException {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet request = new HttpGet(urlString);
HttpResponse response = httpClient.execute(request);
return response.getEntity().getContent();
}
}
It's always a good practice to Program to an interface, not an implementation and Spring Framework uses this practice by providing quite a lot of these interfaces, HandlerInterceptor
is one of them. Some of these interfaces are richer than others. So if you as a client want to provide a custom implementation for them and only care for a few of their methods, you would end up with a few actual implementations and a lot of empty implementations.
For example, suppose you want to provide an implementation for preHandle
method and don't care about the other two. Unfortunately you should provide some empty implementations for the other two:
public class CustomHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
// Some complex logic
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
}
}
Those empty implementations would cause greater boilerplate codes when you're implementing even more richer interfaces, like WebMvcConfigurer
with 10+
abstract methods, imagine the loads of empty methods.
In order to solve this problem, Spring Framework usually provides a corresponding abstract Adapter for those interfaces, like HandlerInterceptorAdaptor
for HandlerInterceptor
interface or WebMvcConfigurerAdapter
for WebMvcConfigurer
. Those adapters are just a bunch of default and simplified implementations for all methods of those interfaces. You can refactor the preceding code using the provided adapter:
public class CustomHandlerInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
// Some complex logic
}
}
Since those empty implementations are provided by the HandlerInterceptorAdapter
class, you just need to provide your implementation for preHandle
method.
As I said, this is a recurring theme in the Spring Framework, some of the common examples are:
Best Answer
The easiest way would probably be to put your web resources into the assets folder then call:
For Complete Communication between Java and Webview See This
Update: The assets folder is usually the following folder:
<project>/src/main/assets
This can be changed in the asset folder configuration setting in your<app>.iml
file as:<option name=”ASSETS_FOLDER_RELATIVE_PATH” value=”/src/main/assets” />
See Article Where to place the assets folder in Android Studio