pull/605/head
jhengazuki 5 months ago
parent ba90484dbb
commit 0a029fd2d8
  1. 120
      app/src/main/java/com/fongmi/android/tv/model/LiveViewModel.java
  2. 7
      app/src/main/java/com/fongmi/android/tv/model/SiteViewModel.java

@ -20,48 +20,58 @@ import com.github.catvod.net.OkHttp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.EnumMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class LiveViewModel extends ViewModel {
private static final int LIVE = 0;
private static final int EPG = 1;
private static final int URL = 2;
private static final int XML = 3;
private enum TaskType {
LIVE(Constant.TIMEOUT_LIVE),
EPG(Constant.TIMEOUT_EPG),
XML(Constant.TIMEOUT_XML),
URL(Constant.TIMEOUT_PARSE_LIVE);
final long timeout;
TaskType(long timeout) {
this.timeout = timeout;
}
}
private final List<SimpleDateFormat> formatTime;
private final Map<TaskType, Future<?>> futures;
private final SimpleDateFormat formatDate;
private final ExecutorService executor;
public MutableLiveData<Channel> url;
public MutableLiveData<Boolean> xml;
public MutableLiveData<Live> live;
public MutableLiveData<Epg> epg;
private ExecutorService executor1;
private ExecutorService executor2;
private ExecutorService executor3;
private ExecutorService executor4;
public final MutableLiveData<Channel> url;
public final MutableLiveData<Boolean> xml;
public final MutableLiveData<Live> live;
public final MutableLiveData<Epg> epg;
public LiveViewModel() {
this.live = new MutableLiveData<>();
this.epg = new MutableLiveData<>();
this.url = new MutableLiveData<>();
this.xml = new MutableLiveData<>();
this.url = new MutableLiveData<>();
this.formatTime = new ArrayList<>();
this.futures = new EnumMap<>(TaskType.class);
this.executor = Executors.newFixedThreadPool(4);
this.formatDate = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
this.formatTime.add(new SimpleDateFormat("yyyy-MM-ddHH:mm", Locale.getDefault()));
this.formatTime.add(new SimpleDateFormat("yyyy-MM-ddHH:mm:ss", Locale.getDefault()));
}
public void getLive(Live item) {
execute(LIVE, () -> {
execute(TaskType.LIVE, () -> {
LiveParser.start(item.recent());
setTimeZone(item);
verify(item);
@ -70,7 +80,7 @@ public class LiveViewModel extends ViewModel {
}
public void getXml(Live item) {
execute(XML, () -> {
execute(TaskType.XML, () -> {
boolean result = false;
for (String url : item.getEpgXml()) if (parseXml(item, url)) result = true;
return result;
@ -88,14 +98,14 @@ public class LiveViewModel extends ViewModel {
public void getEpg(Channel item) {
String date = formatDate.format(new Date());
String url = item.getEpg().replace("{date}", date);
execute(EPG, () -> {
execute(TaskType.EPG, () -> {
if (url.startsWith("http") && !item.getData().equal(date)) item.setData(Epg.objectFrom(OkHttp.string(url), item.getTvgId(), formatTime));
return item.getData().selected();
});
}
public void getUrl(Channel item) {
execute(URL, () -> {
execute(TaskType.URL, () -> {
item.setMsg(null);
Source.get().stop();
item.setUrl(Source.get().fetch(item));
@ -104,7 +114,7 @@ public class LiveViewModel extends ViewModel {
}
public void getUrl(Channel item, EpgData data) {
execute(URL, () -> {
execute(TaskType.URL, () -> {
item.setMsg(null);
Source.get().stop();
item.setUrl(item.getCatchup().format(Source.get().fetch(item), data));
@ -122,63 +132,43 @@ public class LiveViewModel extends ViewModel {
}
private void verify(Live item) {
Iterator<Group> iterator = item.getGroups().iterator();
while (iterator.hasNext()) if (iterator.next().isEmpty()) iterator.remove();
item.getGroups().removeIf(Group::isEmpty);
if (item.getGroups().isEmpty() || item.getGroups().get(0).isKeep()) return;
item.getGroups().add(0, Group.create(R.string.keep));
LiveConfig.get().setKeep(item.getGroups());
}
private void execute(int type, Callable<?> callable) {
switch (type) {
case LIVE:
if (executor1 != null) executor1.shutdownNow();
executor1 = Executors.newFixedThreadPool(2);
executor1.execute(runnable(type, callable, executor1));
break;
case EPG:
if (executor2 != null) executor2.shutdownNow();
executor2 = Executors.newFixedThreadPool(2);
executor2.execute(runnable(type, callable, executor2));
break;
case URL:
if (executor3 != null) executor3.shutdownNow();
executor3 = Executors.newFixedThreadPool(2);
executor3.execute(runnable(type, callable, executor3));
break;
case XML:
if (executor4 != null) executor4.shutdownNow();
executor4 = Executors.newFixedThreadPool(2);
executor4.execute(runnable(type, callable, executor4));
break;
}
}
private Runnable runnable(int type, Callable<?> callable, ExecutorService executor) {
return () -> {
private <T> void execute(TaskType type, Callable<T> callable) {
Future<?> oldFuture = futures.get(type);
if (oldFuture != null && !oldFuture.isDone()) oldFuture.cancel(true);
final Future<T> newFuture = executor.submit(callable);
futures.put(type, newFuture);
executor.execute(() -> {
try {
if (Thread.interrupted()) return;
if (type == EPG) epg.postValue((Epg) executor.submit(callable).get(Constant.TIMEOUT_EPG, TimeUnit.MILLISECONDS));
if (type == LIVE) live.postValue((Live) executor.submit(callable).get(Constant.TIMEOUT_LIVE, TimeUnit.MILLISECONDS));
if (type == XML) xml.postValue((Boolean) executor.submit(callable).get(Constant.TIMEOUT_XML, TimeUnit.MILLISECONDS));
if (type == URL) url.postValue((Channel) executor.submit(callable).get(Constant.TIMEOUT_PARSE_LIVE, TimeUnit.MILLISECONDS));
T result = newFuture.get(type.timeout, TimeUnit.MILLISECONDS);
if (newFuture.isCancelled()) return;
if (type == TaskType.EPG) epg.postValue((Epg) result);
else if (type == TaskType.LIVE) live.postValue((Live) result);
else if (type == TaskType.XML) xml.postValue((Boolean) result);
else if (type == TaskType.URL) url.postValue((Channel) result);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (Throwable e) {
if (e instanceof InterruptedException || Thread.interrupted()) return;
if (newFuture.isCancelled()) return;
if (e.getCause() instanceof ExtractException) url.postValue(Channel.error(e.getCause().getMessage()));
else if (type == URL) url.postValue(new Channel());
if (type == LIVE) live.postValue(new Live());
if (type == EPG) epg.postValue(new Epg());
if (type == XML) xml.postValue(false);
else if (type == TaskType.URL) url.postValue(new Channel());
else if (type == TaskType.LIVE) live.postValue(new Live());
else if (type == TaskType.EPG) epg.postValue(new Epg());
else if (type == TaskType.XML) xml.postValue(false);
e.printStackTrace();
}
};
});
}
@Override
protected void onCleared() {
if (executor1 != null) executor1.shutdownNow();
if (executor2 != null) executor2.shutdownNow();
if (executor3 != null) executor3.shutdownNow();
if (executor4 != null) executor4.shutdownNow();
super.onCleared();
for (Future<?> future : futures.values()) if (future != null) future.cancel(true);
if (executor != null) executor.shutdownNow();
}
}
}

@ -291,10 +291,12 @@ public class SiteViewModel extends ViewModel {
executor.execute(() -> {
try {
Result taskResult = future.get(Constant.TIMEOUT_VOD, TimeUnit.MILLISECONDS);
if (!future.isCancelled()) result.postValue(taskResult);
if (future.isCancelled()) return;
result.postValue(taskResult);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (Throwable e) {
if (future.isCancelled()) return;
if (e.getCause() instanceof ExtractException) result.postValue(Result.error(e.getCause().getMessage()));
else result.postValue(Result.empty());
e.printStackTrace();
@ -304,7 +306,8 @@ public class SiteViewModel extends ViewModel {
@Override
protected void onCleared() {
if (executor != null) executor.shutdownNow();
super.onCleared();
if (future != null) future.cancel(true);
if (executor != null) executor.shutdownNow();
}
}

Loading…
Cancel
Save